Adds support for multiple view modes

Adds mulitple view modes based on zoom-level.  This allows for easy
drilling into a device for more detail or zooming-out for a overview.

* Adds support for multi-site and device modes
* Adds icons to remote device in device detail
* Adds site widget
* Adds link between sites
* Adds toolboxes for inventory, site, and applications
* Adds rack mode
* Adds UI for adding processes to devices
* Adds copy and paste support
* Adds streams
This commit is contained in:
Ben Thomasson 2017-08-11 09:51:40 -04:00
parent 8fb54efa8e
commit 9dc4e22fe6
No known key found for this signature in database
GPG Key ID: 5818EF4CC895D5F5
62 changed files with 8207 additions and 132 deletions

View File

@ -28,8 +28,8 @@ istanbul:
cp vendor/*.js js/
simple-server:
python -m SimpleHTTPServer
simple-server: lint main lessc
python -m SimpleHTTPServer 8080
deploy: main

View File

@ -0,0 +1,19 @@
finite_state_machine_id: 131
name: fsm
states:
- id: 2
label: Ready
x: 517
y: 588
- id: 3
label: Disable
x: 770
y: 455
- id: 1
label: Start
x: 507
y: 336
transitions:
- from_state: Start
label: start
to_state: Ready

View File

@ -0,0 +1,65 @@
finite_state_machine_id: 130
name: mode
states:
- id: 1
label: Start
x: 568
y: -379
- id: 2
label: Interface
x: 340
y: 1053
- id: 3
label: Rack
x: 571
y: 486
- id: 4
label: Process
x: 833
y: 1051
- id: 5
label: MultiSite
x: 569
y: -88
- id: 6
label: Device
x: 558
y: 821
- id: 7
label: Site
x: 564
y: 201
transitions:
- from_state: Rack
label: onMouseWheel
to_state: Site
- from_state: MultiSite
label: onMouseWheel
to_state: Site
- from_state: Device
label: onMouseWheel
to_state: Process
- from_state: Site
label: onMouseWheel
to_state: Rack
- from_state: Device
label: onMouseWheel
to_state: Interface
- from_state: Rack
label: onMouseWheel
to_state: Device
- from_state: Interface
label: onMouseWheel
to_state: Device
- from_state: Device
label: onMouseWheel
to_state: Rack
- from_state: Start
label: start
to_state: MultiSite
- from_state: Process
label: onMouseWheel
to_state: Device
- from_state: Site
label: onMouseWheel
to_state: MultiSite

View File

@ -0,0 +1,72 @@
finite_state_machine_id: 131
name: fsm
states:
- id: 5
label: Selected2
x: 220
y: 810
- id: 7
label: EditLabel
x: 600
y: 934
- id: 2
label: Ready
x: 532
y: 560
- id: 3
label: Disable
x: 760
y: 468
- id: 6
label: Selected3
x: 249
y: 1047
- id: 4
label: Selected1
x: 214
y: 566
- id: 1
label: Start
x: 582
y: 334
- id: 8
label: Move
x: -69
y: 861
transitions:
- from_state: Selected1
label: onMouseMove
to_state: Move
- from_state: Selected3
label: onMouseMove
to_state: Move
- from_state: Move
label: onMouseUp
to_state: Selected2
- from_state: Start
label: start
to_state: Ready
- from_state: Ready
label: onMouseDown
to_state: Selected1
- from_state: Selected1
label: onMouseUp
to_state: Selected2
- from_state: Selected2
label: onMouseDown
to_state: Selected3
- from_state: EditLabel
label: onKeyDown
to_state: Selected2
- from_state: Selected3
label: onMouseUp
to_state: EditLabel
- from_state: EditLabel
label: onMouseDown
to_state: Ready
- from_state: Selected2
label: onMouseDown
to_state: Ready
- from_state: Selected2
label: onKeyDown
to_state: Ready

View File

@ -0,0 +1,72 @@
finite_state_machine_id: 131
name: fsm
states:
- id: 5
label: Selected2
x: 220
y: 810
- id: 7
label: EditLabel
x: 600
y: 934
- id: 2
label: Ready
x: 532
y: 560
- id: 3
label: Disable
x: 760
y: 468
- id: 6
label: Selected3
x: 249
y: 1047
- id: 4
label: Selected1
x: 214
y: 566
- id: 1
label: Start
x: 582
y: 334
- id: 8
label: Move
x: -69
y: 861
transitions:
- from_state: Selected1
label: onMouseMove
to_state: Move
- from_state: Selected3
label: onMouseMove
to_state: Move
- from_state: Move
label: onMouseUp
to_state: Selected2
- from_state: Start
label: start
to_state: Ready
- from_state: Ready
label: onMouseDown
to_state: Selected1
- from_state: Selected1
label: onMouseUp
to_state: Selected2
- from_state: Selected2
label: onMouseDown
to_state: Selected3
- from_state: EditLabel
label: onKeyDown
to_state: Selected2
- from_state: Selected3
label: onMouseUp
to_state: EditLabel
- from_state: EditLabel
label: onMouseDown
to_state: Ready
- from_state: Selected2
label: onMouseDown
to_state: Ready
- from_state: Selected2
label: onKeyDown
to_state: Ready

View File

@ -0,0 +1,42 @@
finite_state_machine_id: 82
name: src/transition
states:
- id: 4
label: Connecting
x: 344
y: 312
- id: 5
label: Selecting
x: 311
y: 23
- id: 1
label: Ready
x: 36
y: 28
- id: 3
label: Connected
x: 55
y: 317
- id: 2
label: Start
x: 43
y: -188
transitions:
- from_state: Ready
label: onNewStream
to_state: Selecting
- from_state: Start
label: start
to_state: Ready
- from_state: Connected
label: start
to_state: Ready
- from_state: Connecting
label: onMouseUp
to_state: Ready
- from_state: Connecting
label: onMouseUp
to_state: Connected
- from_state: Selecting
label: onMouseUp
to_state: Connecting

View File

@ -0,0 +1,49 @@
finite_state_machine_id: 120
name: toolbox
states:
- id: 6
label: Dropping
x: 1197
y: 427
- id: 4
label: Selected
x: 889
y: 713
- id: 2
label: Ready
x: 892
y: 429
- id: 3
label: Scrolling
x: 567
y: 431
- id: 1
label: Start
x: 892
y: 216
- id: 5
label: Move
x: 1197
y: 708
transitions:
- from_state: Start
label: start
to_state: Ready
- from_state: Move
label: onMouseUp
to_state: Dropping
- from_state: Dropping
label: start
to_state: Ready
- from_state: Ready
label: onMouseDown
to_state: Selected
- from_state: Ready
label: onMouseWheel
to_state: Scrolling
- from_state: Scrolling
label: start
to_state: Ready
- from_state: Selected
label: onMouseMove
to_state: Move

View File

@ -5,7 +5,7 @@
<script src="js/bundle.js"></script>
<script src="js/vendor.bundle.js"></script>
</head>
<body>
<body style="margin: 0px">
<awx-network-ui></awx-network-ui>
</body>
</html>

View File

@ -21,7 +21,8 @@
"mathjs": "",
"reconnectingwebsocket": "^1.0.0",
"require": "",
"webpack": ""
"webpack": "",
"titlecase": ""
},
"devDependencies": {
"eslint": "^3.17.1",

View File

@ -0,0 +1,5 @@
function configuration () {
return { restrict: 'A', templateUrl: '/static/network_ui/widgets/configuration.html' };
}
exports.configuration = configuration;

View File

@ -0,0 +1,5 @@
function deviceDetail () {
return { restrict: 'A', templateUrl: '/static/network_ui/widgets/device_detail.html' };
}
exports.deviceDetail = deviceDetail;

View File

@ -0,0 +1,72 @@
var inherits = require('inherits');
var fsm = require('./fsm.js');
var models = require('./models.js');
function _State () {
}
inherits(_State, fsm._State);
function _Ready () {
this.name = 'Ready';
}
inherits(_Ready, _State);
var Ready = new _Ready();
exports.Ready = Ready;
function _Disable () {
this.name = 'Disable';
}
inherits(_Disable, _State);
var Disable = new _Disable();
exports.Disable = Disable;
function _Start () {
this.name = 'Start';
}
inherits(_Start, _State);
var Start = new _Start();
exports.Start = Start;
_Start.prototype.start = function (controller) {
controller.changeState(Ready);
};
_Start.prototype.start.transitions = ['Ready'];
_Ready.prototype.onPasteProcess = function (controller, msg_type, message) {
console.log([msg_type, message]);
var i=0;
var devices = controller.scope.devices;
var device = null;
var x = controller.scope.scaledX;
var y = controller.scope.scaledY;
var app = null;
for(i=0; i < devices.length; i++) {
device = devices[i];
if (device.is_selected(x, y)) {
console.log(device);
app = new models.Application(device.process_id_seq(),
message.process.name,
message.process.type,
controller.scope.scaledX,
controller.scope.scaledY);
device.processes.push(app);
console.log(device.processes);
break;
} else {
console.log([x,y, device.x, device.y]);
}
}
};

View File

@ -2,6 +2,7 @@ var inherits = require('inherits');
var fsm = require('./fsm.js');
var models = require('./models.js');
var messages = require('./messages.js');
var titlecase = require('titlecase');
function _State () {
}
@ -57,6 +58,14 @@ inherits(_Ready, _State);
var Ready = new _Ready();
exports.Ready = Ready;
function _Disable () {
this.name = 'Disable';
}
inherits(_Disable, _State);
var Disable = new _Disable();
exports.Disable = Disable;
function _EditLabel () {
this.name = 'EditLabel';
}
@ -78,6 +87,11 @@ inherits(_Placing, _State);
var Placing = new _Placing();
exports.Placing = Placing;
_State.prototype.onUnselectAll = function (controller, msg_type, $event) {
controller.changeState(Ready);
controller.next_controller.handle_message(msg_type, $event);
};
_Resize.prototype.onMouseUp = function (controller, msg_type, $event) {
@ -119,7 +133,8 @@ _Resize.prototype.onMouseMove = function (controller) {
groups[i].y2 = groups[i].y2 + diffY;
}
membership_old_new = groups[i].update_membership(controller.scope.devices);
membership_old_new = groups[i].update_membership(controller.scope.devices,
controller.scope.groups);
for(j = 0; j < membership_old_new[0].length; j++) {
membership_old_new[0][j].selected = false;
}
@ -145,6 +160,16 @@ _Resize.prototype.onMouseMove = function (controller) {
controller.scope.pressedScaledY = controller.scope.scaledY;
};
_Resize.prototype.start = function (controller) {
var groups = controller.scope.selected_groups;
var i = 0;
for (i = 0; i < groups.length; i++) {
groups[i].moving = true;
}
};
_Resize.prototype.end = function (controller) {
var groups = controller.scope.selected_groups;
@ -156,6 +181,10 @@ _Resize.prototype.end = function (controller) {
groups[i].devices[j].selected = false;
}
}
for (i = 0; i < groups.length; i++) {
groups[i].moving = false;
}
};
@ -242,7 +271,8 @@ _Move.prototype.onMouseMove = function (controller) {
groups[i].x2 = groups[i].x2 + diffX;
groups[i].y2 = groups[i].y2 + diffY;
membership_old_new = groups[i].update_membership(controller.scope.devices);
membership_old_new = groups[i].update_membership(controller.scope.devices,
controller.scope.groups);
for(j = 0; j < membership_old_new[0].length; j++) {
membership_old_new[0][j].selected = false;
}
@ -281,6 +311,16 @@ _Move.prototype.onMouseDown = function (controller) {
};
_Move.prototype.onMouseDown.transitions = ['Selected1'];
_Move.prototype.start = function (controller) {
var groups = controller.scope.selected_groups;
var i = 0;
for (i = 0; i < groups.length; i++) {
groups[i].moving = true;
}
};
_Move.prototype.end = function (controller) {
var groups = controller.scope.selected_groups;
@ -292,6 +332,10 @@ _Move.prototype.end = function (controller) {
groups[i].devices[j].selected = false;
}
}
for (i = 0; i < groups.length; i++) {
groups[i].moving = false;
}
};
@ -363,12 +407,48 @@ _Ready.prototype.onMouseDown = function (controller, msg_type, $event) {
_Ready.prototype.onMouseDown.transitions = ['Selected1', 'CornerSelected'];
_Ready.prototype.onNewGroup = function (controller) {
_Ready.prototype.onNewGroup = function (controller, msg_type, message) {
controller.scope.hide_groups = false;
controller.scope.new_group_type = message.type;
controller.changeState(Placing);
};
_Ready.prototype.onNewGroup.transitions = ['Placing'];
_Ready.prototype.onPasteGroup = function (controller, msg_type, message) {
var scope = controller.scope;
scope.hide_groups = false;
scope.pressedX = scope.mouseX;
scope.pressedY = scope.mouseY;
scope.pressedScaledX = scope.scaledX;
scope.pressedScaledY = scope.scaledY;
var group = new models.Group(controller.scope.group_id_seq(),
message.group.name,
message.group.type,
scope.scaledX,
scope.scaledY,
scope.scaledX + message.group.x2,
scope.scaledY + message.group.y2,
false);
scope.send_control_message(new messages.GroupCreate(scope.client_id,
group.id,
group.x1,
group.y1,
group.x2,
group.y2,
group.name,
group.type));
scope.groups.push(group);
scope.selected_groups.push(group);
group.selected = true;
controller.changeState(Selected2);
};
_Ready.prototype.onPasteGroup.transitions = ['Selected2'];
_EditLabel.prototype.start = function (controller) {
@ -482,6 +562,8 @@ _Selected2.prototype.onKeyDown = function (controller, msg_type, $event) {
groups[i].y2,
groups[i].name));
}
} else {
controller.next_controller.handle_message(msg_type, $event);
}
};
_Selected2.prototype.onKeyDown.transitions = ['Ready'];
@ -502,7 +584,8 @@ _Placing.prototype.onMouseDown = function (controller) {
var id = scope.group_id_seq();
group = new models.Group(id,
"Group" + id,
titlecase.toTitleCase("" + scope.new_group_type + id),
scope.new_group_type,
scope.scaledX,
scope.scaledY,
scope.scaledX,
@ -514,13 +597,16 @@ _Placing.prototype.onMouseDown = function (controller) {
group.y1,
group.x2,
group.y2,
group.name));
group.name,
group.type));
scope.groups.push(group);
scope.selected_groups.push(group);
group.selected = true;
group.selected_corner = models.BOTTOM_RIGHT;
controller.scope.new_group_type = null;
controller.changeState(Resize);
};
_Placing.prototype.onMouseDown.transitions = ['CornerSelected'];

View File

@ -43,11 +43,19 @@ _Enabled.prototype.onKeyDown = function(controller, msg_type, $event) {
var scope = controller.scope;
if ($event.key === 'c' && ($event.ctrlKey || $event.metaKey)) {
scope.first_controller.handle_message("CopySelected", $event);
}
if ($event.key === 'l') {
scope.first_controller.handle_message("NewLink", $event);
return;
}
if ($event.key === 'm') {
scope.first_controller.handle_message("NewStream", $event);
}
if ($event.key === 'd') {
scope.debug.hidden = !scope.debug.hidden;
return;
@ -74,13 +82,28 @@ _Enabled.prototype.onKeyDown = function(controller, msg_type, $event) {
return;
}
else if ($event.key === 'a') {
scope.first_controller.handle_message("NewDevice", new messages.NewDevice("rack"));
scope.first_controller.handle_message("NewGroup", new messages.NewGroup("rack"));
return;
}
else if ($event.key === 'h') {
scope.first_controller.handle_message("NewDevice", new messages.NewDevice("host"));
return;
}
else if ($event.key === 'g') {
scope.first_controller.handle_message("NewGroup", new messages.NewGroup("group"));
return;
}
else if ($event.key === 'e') {
scope.first_controller.handle_message("NewGroup", new messages.NewGroup("site"));
return;
}
else if ($event.key === '0') {
scope.panX = 0;
scope.panY = 0;
scope.current_scale = 1.0;
scope.updateScaledXY();
scope.updatePanAndScale();
}
controller.next_controller.handle_message(msg_type, $event);
};

View File

@ -0,0 +1,5 @@
function inventoryToolboxClipPath () {
return { restrict: 'A', templateUrl: '/static/network_ui/widgets/inventory_toolbox_clip_path.html' };
}
exports.inventoryToolboxClipPath = inventoryToolboxClipPath;

View File

@ -0,0 +1,5 @@
function inventoryToolbox () {
return { restrict: 'A', templateUrl: '/static/network_ui/widgets/inventory_toolbox.html' };
}
exports.inventoryToolbox = inventoryToolbox;

View File

@ -1,6 +1,11 @@
var networkUI = require('./network.ui.app.js');
var networkWidgets = require('./network.widgets.app.js');
var tablesUI = require('./tables.ui.app.js');
var tower = require('./tower.app.js');
var ngTouch = require('./ngTouch.js');
exports.networkUI = networkUI.networkUI;
+exports.tablesUI = tablesUI.tablesUI;
exports.tablesUI = tablesUI.tablesUI;
exports.tower = tower.tower;
exports.ngTouch = ngTouch;
exports.networkWidgets = networkWidgets;

View File

@ -0,0 +1,5 @@
function map () {
return { restrict: 'A', templateUrl: '/static/network_ui/widgets/map.html' };
}
exports.map = map;

View File

@ -247,6 +247,38 @@ function NewDevice(type) {
}
exports.NewDevice = NewDevice;
function PasteDevice(device) {
this.device = device;
}
exports.PasteDevice = PasteDevice;
function PasteProcess(process) {
this.process = process;
}
exports.PasteProcess = PasteProcess;
function NewGroup(type) {
this.type = type;
}
exports.NewGroup = NewGroup;
function PasteGroup(group) {
this.group = group;
}
exports.PasteGroup = PasteGroup;
function PasteRack(group) {
this.group = group;
}
exports.PasteRack = PasteRack;
function PasteSite(group) {
this.group = group;
}
exports.PasteSite = PasteSite;
function GroupMove(sender, id, x1, y1, x2, y2, previous_x1, previous_y1, previous_x2, previous_y2) {
this.msg_type = "GroupMove";
this.sender = sender;
@ -262,7 +294,7 @@ function GroupMove(sender, id, x1, y1, x2, y2, previous_x1, previous_y1, previou
}
exports.GroupMove = GroupMove;
function GroupCreate(sender, id, x1, y1, x2, y2, name) {
function GroupCreate(sender, id, x1, y1, x2, y2, name, type) {
this.msg_type = "GroupCreate";
this.sender = sender;
this.id = id;
@ -271,6 +303,7 @@ function GroupCreate(sender, id, x1, y1, x2, y2, name) {
this.x2 = x2;
this.y2 = y2;
this.name = name;
this.type = type;
}
exports.GroupCreate = GroupCreate;
@ -328,3 +361,46 @@ function TableCellEdit(sender, sheet, col, row, old_value, new_value) {
this.new_value = new_value;
}
exports.TableCellEdit = TableCellEdit;
function StreamCreate(sender, id, from_id, to_id, label) {
this.msg_type = "StreamCreate";
this.sender = sender;
this.id = id;
this.from_id = from_id;
this.to_id = to_id;
this.label = label;
}
exports.StreamCreate = StreamCreate;
function StreamDestroy(sender, id, from_id, to_id, label) {
this.msg_type = "StreamDestroy";
this.sender = sender;
this.id = id;
this.from_id = from_id;
this.to_id = to_id;
this.label = label;
}
exports.StreamDestroy = StreamDestroy;
function StreamLabelEdit(sender, id, label, previous_label) {
this.msg_type = "StreamLabelEdit";
this.sender = sender;
this.id = id;
this.label = label;
this.previous_label = previous_label;
}
exports.StreamLabelEdit = StreamLabelEdit;
function StreamSelected(sender, id) {
this.msg_type = "StreamSelected";
this.sender = sender;
this.id = id;
}
exports.StreamSelected = StreamSelected;
function StreamUnSelected(sender, id) {
this.msg_type = "StreamUnSelected";
this.sender = sender;
this.id = id;
}
exports.StreamUnSelected = StreamUnSelected;

View File

@ -0,0 +1,201 @@
var inherits = require('inherits');
var fsm = require('./fsm.js');
var move = require('./move.js');
var group = require('./group.js');
var rack_fsm = require('./rack.fsm.js');
var site_fsm = require('./site.fsm.js');
function _State () {
}
inherits(_State, fsm._State);
function _Start () {
this.name = 'Start';
}
inherits(_Start, _State);
var Start = new _Start();
exports.Start = Start;
function _Interface () {
this.name = 'Interface';
}
inherits(_Interface, _State);
var Interface = new _Interface();
exports.Interface = Interface;
function _Site () {
this.name = 'Site';
}
inherits(_Site, _State);
var Site = new _Site();
exports.Site = Site;
function _Process () {
this.name = 'Process';
}
inherits(_Process, _State);
var Process = new _Process();
exports.Process = Process;
function _MultiSite () {
this.name = 'MultiSite';
}
inherits(_MultiSite, _State);
var MultiSite = new _MultiSite();
exports.MultiSite = MultiSite;
function _Rack () {
this.name = 'Rack';
}
inherits(_Rack, _State);
var Rack = new _Rack();
exports.Rack = Rack;
function _Device () {
this.name = 'Device';
}
inherits(_Device, _State);
var Device = new _Device();
exports.Device = Device;
_State.prototype.start = function (controller) {
controller.scope.current_mode = controller.state.name;
};
_Start.prototype.start = function (controller) {
controller.changeState(Rack);
};
_Start.prototype.start.transitions = ['MultiSite'];
_Interface.prototype.onMouseWheel = function (controller, msg_type, $event) {
//controller.changeState(Device);
controller.next_controller.handle_message(msg_type, $event);
};
_Interface.prototype.onMouseWheel.transitions = ['Device'];
_Site.prototype.start = function (controller) {
controller.scope.current_mode = controller.state.name;
controller.scope.rack_toolbox.enabled = true;
controller.scope.rack_controller.changeState(rack_fsm.Ready);
};
_Site.prototype.end = function (controller) {
controller.scope.rack_toolbox.enabled = false;
controller.scope.rack_controller.changeState(rack_fsm.Disable);
};
_Site.prototype.onMouseWheel = function (controller, msg_type, $event) {
if (controller.scope.current_scale < 0.1) {
controller.changeState(MultiSite);
} else if (controller.scope.current_scale > 0.5) {
controller.changeState(Rack);
}
controller.next_controller.handle_message(msg_type, $event);
};
_Site.prototype.onMouseWheel.transitions = ['MultiSite', 'Rack'];
_Process.prototype.onMouseWheel = function (controller, msg_type, $event) {
controller.next_controller.handle_message(msg_type, $event);
//controller.changeState(Device);
};
_Process.prototype.onMouseWheel.transitions = ['Device'];
_MultiSite.prototype.start = function (controller) {
controller.scope.current_mode = controller.state.name;
controller.scope.site_toolbox.enabled = true;
controller.scope.site_controller.changeState(site_fsm.Ready);
};
_MultiSite.prototype.end = function (controller) {
controller.scope.site_toolbox.enabled = false;
controller.scope.site_controller.changeState(site_fsm.Disable);
};
_MultiSite.prototype.onMouseWheel = function (controller, msg_type, $event) {
if (controller.scope.current_scale > 0.1) {
controller.changeState(Site);
}
controller.next_controller.handle_message(msg_type, $event);
};
_MultiSite.prototype.onMouseWheel.transitions = ['Site'];
_Device.prototype.start = function (controller) {
controller.scope.current_mode = controller.state.name;
controller.scope.app_toolbox.enabled = true;
};
_Device.prototype.end = function (controller) {
controller.scope.app_toolbox.enabled = false;
};
_Device.prototype.onMouseWheel = function (controller, msg_type, $event) {
//controller.changeState(Process);
//controller.changeState(Interface);
//controller.changeState(Site);
if (controller.scope.current_scale < 5) {
controller.changeState(Rack);
}
controller.next_controller.handle_message(msg_type, $event);
};
_Device.prototype.onMouseWheel.transitions = ['Process', 'Interface', 'Rack'];
_Rack.prototype.start = function (controller) {
controller.scope.current_mode = controller.state.name;
controller.scope.inventory_toolbox.enabled = true;
controller.scope.move_controller.changeState(move.Ready);
controller.scope.group_controller.changeState(group.Ready);
};
_Rack.prototype.end = function (controller) {
controller.scope.inventory_toolbox.enabled = false;
controller.scope.move_controller.changeState(move.Disable);
controller.scope.group_controller.changeState(group.Disable);
};
_Rack.prototype.onMouseWheel = function (controller, msg_type, $event) {
if (controller.scope.current_scale < 0.5) {
controller.changeState(Site);
}
if (controller.scope.current_scale > 5) {
controller.changeState(Device);
}
controller.next_controller.handle_message(msg_type, $event);
};
_Rack.prototype.onMouseWheel.transitions = ['Site', 'Device'];

View File

@ -17,10 +17,14 @@ function Device(id, name, x, y, type) {
this.edit_label = false;
this.status = null;
this.working = false;
this.moving = false;
this.icon = false;
this.tasks = [];
this.shape = type === "router" ? "circular" : "rectangular";
this.interface_seq = util.natural_numbers(0);
this.interfaces = [];
this.process_id_seq = util.natural_numbers(0);
this.processes = [];
}
exports.Device = Device;
@ -47,6 +51,18 @@ function Interface(id, name) {
}
exports.Interface = Interface;
Interface.prototype.remote_interface = function () {
if (this.link === null) {
return null;
}
if (this.link.to_interface === this) {
return this.link.from_interface;
} else {
return this.link.to_interface;
}
};
Interface.prototype.is_selected = function (x, y) {
if (this.link === null || this.device === null) {
@ -65,6 +81,9 @@ Interface.prototype.dot = function () {
if (this.link === null || this.device === null) {
return;
}
if (this.link.to_device === null || this.link.from_device === null) {
return;
}
var p;
if (this.device.shape === "circular") {
@ -309,18 +328,24 @@ exports.Task = Task;
Task.prototype.describeArc = util.describeArc;
function Group(id, name, x1, y1, x2, y2, selected) {
function Group(id, name, type, x1, y1, x2, y2, selected) {
this.id = id;
this.name = name;
this.type = type;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.selected = selected;
this.moving = false;
this.highlighted = false;
this.fsm = null;
this.selected_corner = null;
this.devices = [];
this.links = [];
this.groups = [];
this.streams = [];
this.icon_size = type === 'site' ? 500 : 100;
}
exports.Group = Group;
@ -338,6 +363,19 @@ Group.prototype.is_highlighted = function (x, y) {
};
Group.prototype.is_icon_selected = function (x, y) {
return ((x > this.left_extent() &&
x < this.right_extent() &&
y > this.top_extent() &&
y < this.bottom_extent()) ||
(x > this.centerX() - this.icon_size &&
x < this.centerX() + this.icon_size &&
y > this.centerY() - this.icon_size &&
y < this.centerY() + this.icon_size));
};
var TOP_LEFT = 0;
exports.TOP_LEFT = TOP_LEFT;
var TOP_RIGHT = 1;
@ -377,6 +415,18 @@ Group.prototype.has_corner_selected = function (x, y) {
return false;
};
Group.prototype.corners = function () {
return [{x: this.left_extent(),
y: this.top_extent()},
{x: this.right_extent(),
y: this.top_extent()},
{x: this.left_extent(),
y: this.bottom_extent()},
{x: this.left_extent(),
y: this.bottom_extent()}];
};
Group.prototype.select_corner = function (x, y) {
var corners = [[util.distance(this.x1, this.y1, x, y), TOP_LEFT],
@ -384,8 +434,6 @@ Group.prototype.select_corner = function (x, y) {
[util.distance(this.x1, this.y2, x, y), BOTTOM_LEFT],
[util.distance(this.x2, this.y1, x, y), TOP_RIGHT]];
console.log(corners);
corners.sort(function(a, b) {
return a[0] - b[0];
});
@ -473,7 +521,15 @@ Group.prototype.right_extent = function (scaledX) {
return (this.x1 > x2? this.x1 : x2);
};
Group.prototype.update_membership = function (devices) {
Group.prototype.centerX = function (scaledX) {
return (this.right_extent(scaledX) + this.left_extent(scaledX)) / 2;
};
Group.prototype.centerY = function (scaledY) {
return (this.bottom_extent(scaledY) + this.top_extent(scaledY)) / 2;
};
Group.prototype.update_membership = function (devices, groups) {
var i = 0;
var y1 = this.top_extent();
var x1 = this.left_extent();
@ -491,5 +547,260 @@ Group.prototype.update_membership = function (devices) {
device_ids.push(devices[i].id);
}
}
return [old_devices, this.devices, device_ids];
var old_groups = this.groups;
this.groups = [];
var group_ids = [];
for (i = 0; i < groups.length; i++) {
if (groups[i].left_extent() > x1 &&
groups[i].top_extent() > y1 &&
groups[i].right_extent() < x2 &&
groups[i].bottom_extent() < y2) {
this.groups.push(groups[i]);
group_ids.push(groups[i].id);
}
}
return [old_devices, this.devices, device_ids, old_groups, this.groups, group_ids];
};
function ToolBox(id, name, type, x, y, width, height) {
this.id = id;
this.name = name;
this.type = type;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.items = [];
this.spacing = 200;
this.scroll_offset = 0;
this.selected_item = null;
this.enabled = true;
}
exports.ToolBox = ToolBox;
function Configuration(id, name, type, x, y, content) {
this.id = id;
this.name = name;
this.type = type;
this.x = x;
this.y = y;
this.height = 50;
this.width = 50;
this.size = 50;
this.content = content;
this.selected = null;
this.enabled = true;
this.icon = false;
}
exports.Configuration = Configuration;
function Application(id, name, type, x, y) {
this.id = id;
this.name = name;
this.type = type;
this.x = x;
this.y = y;
this.height = 50;
this.width = 50;
this.size = 50;
this.selected = null;
this.enabled = true;
this.icon = false;
}
exports.Application = Application;
function Stream(id, from_device, to_device, label) {
this.id = id;
this.from_device = from_device;
this.to_device = to_device;
this.selected = false;
this.remote_selected = false;
this.label = label;
this.offset = 0;
}
exports.Stream = Stream;
Stream.prototype.toJSON = function () {
return {to_device: this.to_device.id,
from_device: this.from_device.id};
};
Stream.prototype.slope_rad = function () {
//Return the slope in radians for this transition.
var x1 = this.from_device.x;
var y1 = this.from_device.y;
var x2 = this.to_device.x;
var y2 = this.to_device.y;
return Math.atan2(y2 - y1, x2 - x1) + Math.PI;
};
Stream.prototype.slope = function () {
//Return the slope in degrees for this transition.
var x1 = this.from_device.x;
var y1 = this.from_device.y;
var x2 = this.to_device.x;
var y2 = this.to_device.y;
return Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI + 180;
};
Stream.prototype.flip_text_rotate = function () {
var slope = this.slope();
if (slope > 90 && slope < 270) {
return 180;
} else {
return 0;
}
};
Stream.prototype.flip_text_offset = function () {
var slope = this.slope();
if (slope > 90 && slope < 270) {
return 10;
} else {
return 0;
}
};
Stream.prototype.pslope = function () {
//Return the slope of a perpendicular line to this
//transition
var x1 = this.from_device.x;
var y1 = this.from_device.y;
var x2 = this.to_device.x;
var y2 = this.to_device.y;
var slope = (y2 - y1)/(x2 - x1);
//var intercept = - slope * x1;
var pslope = 1/slope;
return Math.atan(pslope) * 180 / Math.PI + 180;
};
Stream.prototype.perpendicular = function (x, y) {
//Find the perpendicular line through x, y to this transition.
var x1 = this.from_device.x;
var y1 = this.from_device.y;
var x2 = this.to_device.x;
var y2 = this.to_device.y;
var slope = (y2 - y1)/(x2 - x1);
var intercept = y1 - slope * x1;
var pslope = -1/slope;
var pintercept = y - pslope * x;
var xi = (pintercept - intercept) / (slope - pslope);
var yi = pslope * xi + pintercept;
return {x1:x, y1:y, x2: xi, y2: yi};
};
Stream.prototype.is_selected = function (x, y) {
// Is the distance to the mouse location less than 25 if on the label side
// or 5 on the other from the shortest line to the transition?
console.log("is_selected");
var phi = this.slope_rad();
console.log({"phi": phi});
console.log({'x': this.from_device.x, 'y': this.from_device.y});
console.log({'x': this.to_device.x, 'y': this.to_device.y});
console.log({'x': x, 'y': y});
var p1 = util.cartesianToPolar(this.from_device.x, this.from_device.y);
var p2 = util.cartesianToPolar(this.to_device.x, this.to_device.y);
var p3 = util.cartesianToPolar(x, y);
console.log(p1);
p1.theta -= phi;
console.log(p1);
console.log(p2);
p2.theta -= phi;
console.log(p2);
p3.theta -= phi;
p1 = util.polarToCartesian_rad(0, 0, p1.r, p1.theta);
p2 = util.polarToCartesian_rad(0, 0, p2.r, p2.theta);
p3 = util.polarToCartesian_rad(0, 0, p3.r, p3.theta);
p2.y -= this.arc_offset2();
console.log(p1);
console.log(p2);
console.log(p3);
var max_x = Math.max(p1.x, p2.x);
var min_x = Math.min(p1.x, p2.x);
var max_y = Math.max(p1.y, p2.y) + 5;
var min_y = Math.min(p1.y, p2.y) - 25 ;
return p3.x > min_x && p3.x < max_x && p3.y > min_y && p3.y < max_y;
};
Stream.prototype.length = function () {
//Return the length of this transition.
var x1 = this.from_device.x;
var y1 = this.from_device.y;
var x2 = this.to_device.x;
var y2 = this.to_device.y;
return Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2));
};
Stream.prototype.inter_length = function () {
//Return the length of this transition between states.
return this.length() - this.from_device.size - this.to_device.size;
};
Stream.prototype.arc_r = function () {
return this.inter_length();
};
Stream.prototype.arc_r2 = function () {
var offset_to_r = [2, 1, 0.75, 0.6, 0.55, 0.53, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5];
return this.length() * offset_to_r[this.offset];
};
Stream.prototype.arc_offset = function () {
var r = this.arc_r();
var offset = r - (Math.sin(this.arc_angle_rad()) * r);
return offset;
};
Stream.prototype.arc_offset2 = function () {
var r = this.arc_r2();
var theta = Math.acos((this.length() / 2) / r);
var offset = r * (1 - Math.sin(theta));
return offset;
};
Stream.prototype.arc_angle_rad = function () {
return Math.acos((this.inter_length() / 2) / this.arc_r());
};
Stream.prototype.arc_angle_tan_rad = function () {
return Math.PI/2 - Math.acos((this.inter_length() / 2) / this.arc_r());
};
Stream.prototype.arc_angle_tan = function () {
return this.arc_angle_tan_rad() * 180 / Math.PI;
};
Stream.prototype.arc_angle_tan_rad2 = function () {
var r = this.arc_r2();
var l = this.length();
var phi = this.end_arc_angle_rad();
return Math.PI/2 - Math.acos((l/2 - Math.cos(phi) * this.to_device.size) / r);
};
Stream.prototype.arc_angle_tan2 = function () {
return this.arc_angle_tan_rad2() * 180 / Math.PI;
};
Stream.prototype.end_arc_angle_rad = function () {
var r = this.arc_r2();
var l = this.length();
return Math.acos((this.to_device.size / 2) / r) - Math.acos((l/2)/r);
};
Stream.prototype.end_arc_angle = function () {
return this.end_arc_angle_rad() * 180 / Math.PI;
};
Stream.prototype.start_arc_angle_rad = function () {
return Math.acos((this.from_device.size / 2) / this.arc_r2()) - Math.acos((this.length()/2)/this.arc_r2());
};
Stream.prototype.start_arc_angle = function () {
return this.start_arc_angle_rad() * 180 / Math.PI;
};

View File

@ -15,6 +15,13 @@ inherits(_Ready, _State);
var Ready = new _Ready();
exports.Ready = Ready;
function _Disable () {
this.name = 'Disable';
}
inherits(_Disable, _State);
var Disable = new _Disable();
exports.Disable = Disable;
function _Start () {
this.name = 'Start';
}
@ -67,6 +74,13 @@ inherits(_Placing, _State);
var Placing = new _Placing();
exports.Placing = Placing;
_State.prototype.onUnselectAll = function (controller, msg_type, $event) {
controller.changeState(Ready);
controller.next_controller.handle_message(msg_type, $event);
};
_Ready.prototype.onNewDevice = function (controller, msg_type, message) {
var scope = controller.scope;
@ -128,6 +142,47 @@ _Ready.prototype.onNewDevice = function (controller, msg_type, message) {
};
_Ready.prototype.onNewDevice.transitions = ['Placing'];
_Ready.prototype.onPasteDevice = function (controller, msg_type, message) {
var scope = controller.scope;
var device = null;
var intf = null;
var process = null;
var i = 0;
scope.pressedX = scope.mouseX;
scope.pressedY = scope.mouseY;
scope.pressedScaledX = scope.scaledX;
scope.pressedScaledY = scope.scaledY;
device = new models.Device(controller.scope.device_id_seq(),
message.device.name,
scope.scaledX,
scope.scaledY,
message.device.type);
scope.devices.push(device);
scope.send_control_message(new messages.DeviceCreate(scope.client_id,
device.id,
device.x,
device.y,
device.name,
device.type));
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);
}
for (i=0; i < message.device.processes.length; i++) {
process = new models.Application(message.device.processes[i].id,
message.device.processes[i].name,
message.device.processes[i].type, 0, 0);
device.processes.push(process);
}
scope.selected_devices.push(device);
device.selected = true;
controller.changeState(Selected2);
};
_Ready.prototype.onPasteDevice.transitions = ['Selected2'];
_Ready.prototype.onMouseDown = function (controller, msg_type, $event) {
var last_selected = controller.scope.select_items($event.shiftKey);
@ -162,6 +217,29 @@ _Selected2.prototype.onNewDevice = function (controller, msg_type, message) {
};
_Selected2.prototype.onNewDevice.transitions = ['Ready'];
_Selected2.prototype.onCopySelected = function (controller) {
var devices = controller.scope.selected_devices;
var device_copy = null;
var process_copy = null;
var interface_copy = null;
var i = 0;
var j = 0;
for(i=0; i < devices.length; i++) {
device_copy = new models.Device(0, devices[i].name, 0, 0, devices[i].type);
device_copy.icon = true;
for(j=0; j < devices[i].processes.length; j++) {
process_copy = new models.Application(0, devices[i].processes[j].name, devices[i].processes[j].name, 0, 0);
device_copy.processes.push(process_copy);
}
for(j=0; j < devices[i].interfaces.length; j++) {
interface_copy = new models.Interface(devices[i].interfaces[j].id, devices[i].interfaces[j].name);
device_copy.interfaces.push(interface_copy);
}
controller.scope.inventory_toolbox.items.push(device_copy);
}
};
_Selected2.prototype.onMouseDown = function (controller, msg_type, $event) {
var last_selected = null;
@ -256,7 +334,6 @@ _Selected2.prototype.onKeyDown = function (controller, msg_type, $event) {
};
_Selected2.prototype.onKeyDown.transitions = ['Ready'];
_Selected1.prototype.onMouseMove = function (controller) {
controller.changeState(Move);
@ -277,6 +354,33 @@ _Selected1.prototype.onTouchEnd = _Selected1.prototype.onMouseUp;
_Selected1.prototype.onMouseDown = util.noop;
_Move.prototype.start = function (controller) {
var devices = controller.scope.selected_devices;
var i = 0;
var j = 0;
for (i = 0; i < devices.length; i++) {
devices[i].moving = true;
for (j = 0; j < controller.scope.devices.length; j++) {
console.log(Math.pow(devices[i].x - controller.scope.devices[j].x, 2) +
Math.pow(devices[i].y - controller.scope.devices[j].y, 2));
if ((Math.pow(devices[i].x - controller.scope.devices[j].x, 2) +
Math.pow(devices[i].y - controller.scope.devices[j].y, 2)) < 160000) {
controller.scope.devices[j].moving = true;
}
}
}
};
_Move.prototype.end = function (controller) {
var devices = controller.scope.devices;
var i = 0;
for (i = 0; i < devices.length; i++) {
devices[i].moving = false;
}
};
_Move.prototype.onMouseMove = function (controller) {
var devices = controller.scope.selected_devices;
@ -313,7 +417,7 @@ _Move.prototype.onMouseMove = function (controller) {
//TODO: Improve the performance of this code from O(n^2) to O(n) or better
for (i = 0; i < groups.length; i++) {
membership_old_new = groups[i].update_membership(controller.scope.devices);
membership_old_new = groups[i].update_membership(controller.scope.devices, controller.scope.groups);
controller.scope.send_control_message(new messages.GroupMembership(controller.scope.client_id,
groups[i].id,
membership_old_new[2]));

View File

@ -8,13 +8,23 @@ var router = require('./router.directive.js');
var switchd = require('./switch.directive.js');
var host = require('./host.directive.js');
var link = require('./link.directive.js');
var stream = require('./stream.directive.js');
var rack = require('./rack.directive.js');
var rackIcon = require('./rack.icon.directive.js');
var group = require('./group.directive.js');
var site = require('./site.directive.js');
var siteIcon = require('./site.icon.directive.js');
var process = require('./process.directive.js');
var configuration = require('./configuration.directive.js');
var map = require('./map.directive.js');
var deviceDetail = require('./device.detail.directive.js');
var defaultd = require('./default.directive.js');
var quadrants = require('./quadrants.directive.js');
var stencil = require('./stencil.directive.js');
var layer = require('./layer.directive.js');
var button = require('./button.directive.js');
var inventoryToolbox = require('./inventory.toolbox.directive.js');
var inventoryToolboxClipPath = require('./inventory.toolbox.clip.path.directive.js');
var statusLight = require('./status.light.directive.js');
var taskStatus = require('./task.status.directive.js');
var debug = require('./debug.directive.js');
@ -32,13 +42,23 @@ var networkUI = angular.module('networkUI', [
.directive('awxNetSwitch', switchd.switchd)
.directive('awxNetHost', host.host)
.directive('awxNetLink', link.link)
.directive('awxNetStream', stream.stream)
.directive('awxNetRack', rack.rack)
.directive('awxNetGroup', group.group)
.directive('awxNetSite', site.site)
.directive('awxNetSiteIcon', siteIcon.siteIcon)
.directive('awxNetRackIcon', rackIcon.rackIcon)
.directive('awxNetProcess', process.process)
.directive('awxNetConfiguration', configuration.configuration)
.directive('awxNetMap', map.map)
.directive('awxNetDeviceDetail', deviceDetail.deviceDetail)
.directive('awxNetDefault', defaultd.defaultd)
.directive('awxNetQuadrants', quadrants.quadrants)
.directive('awxNetStencil', stencil.stencil)
.directive('awxNetLayer', layer.layer)
.directive('awxNetButton', button.button)
.directive('awxNetInventoryToolbox', inventoryToolbox.inventoryToolbox)
.directive('awxNetInventoryToolboxClipPath', inventoryToolboxClipPath.inventoryToolboxClipPath)
.directive('awxNetStatusLight', statusLight.statusLight)
.directive('awxNetTaskStatus', taskStatus.taskStatus)
.directive('awxNetworkUi', awxNetworkUI.awxNetworkUI);

View File

@ -1,13 +1,16 @@
//console.log = function () { };
var angular = require('angular');
var fsm = require('./fsm.js');
var null_fsm = require('./null.fsm.js');
var mode_fsm = require('./mode.fsm.js');
var device_detail_fsm = require('./device.detail.fsm.js');
var rack_fsm = require('./rack.fsm.js');
var site_fsm = require('./site.fsm.js');
var hotkeys = require('./hotkeys.fsm.js');
var toolbox_fsm = require('./toolbox.fsm.js');
var view = require('./view.js');
var move = require('./move.js');
var link = require('./link.js');
var stream_fsm = require('./stream.fsm.js');
var group = require('./group.js');
var buttons = require('./buttons.js');
var time = require('./time.js');
@ -20,9 +23,10 @@ var ReconnectingWebSocket = require('reconnectingwebsocket');
var NetworkUIController = function($scope, $document, $location, $window) {
window.scope = $scope;
var i = 0;
$scope.api_token = '';
$scope.disconnected = false;
$scope.disconnected = true;
$scope.topology_id = $location.search().topology_id || 0;
// Create a web socket to connect to the backend server
@ -45,6 +49,8 @@ var NetworkUIController = function($scope, $document, $location, $window) {
$scope.onMouseMoveResult = "";
$scope.onMouseMoveResult = "";
$scope.current_scale = 1.0;
$scope.current_mode = null;
$scope.current_location = ["Earth", "Site1", "Spine1", "Eth1"];
$scope.panX = 0;
$scope.panY = 0;
$scope.mouseX = 0;
@ -63,15 +69,8 @@ var NetworkUIController = function($scope, $document, $location, $window) {
$scope.selected_items = [];
$scope.selected_groups = [];
$scope.new_link = null;
$scope.null_controller = new fsm.FSMController($scope, null_fsm.Start, null);
$scope.hotkeys_controller = new fsm.FSMController($scope, hotkeys.Start, $scope.null_controller);
$scope.view_controller = new fsm.FSMController($scope, view.Start, $scope.hotkeys_controller);
$scope.move_controller = new fsm.FSMController($scope, move.Start, $scope.view_controller);
$scope.link_controller = new fsm.FSMController($scope, link.Start, $scope.move_controller);
$scope.group_controller = new fsm.FSMController($scope, group.Start, $scope.link_controller);
$scope.buttons_controller = new fsm.FSMController($scope, buttons.Start, $scope.group_controller);
$scope.time_controller = new fsm.FSMController($scope, time.Start, $scope.buttons_controller);
$scope.first_controller = $scope.time_controller;
$scope.new_stream = null;
$scope.new_group_type = null;
$scope.last_key = "";
$scope.last_key_code = null;
$scope.last_event = null;
@ -89,6 +88,7 @@ var NetworkUIController = function($scope, $document, $location, $window) {
$scope.link_id_seq = util.natural_numbers(0);
$scope.group_id_seq = util.natural_numbers(0);
$scope.message_id_seq = util.natural_numbers(0);
$scope.stream_id_seq = util.natural_numbers(0);
$scope.time_pointer = -1;
$scope.frame = 0;
$scope.recording = false;
@ -99,9 +99,108 @@ var NetworkUIController = function($scope, $document, $location, $window) {
$scope.stencils = [];
$scope.links = [];
$scope.groups = [];
$scope.processes = [];
$scope.configurations = [];
$scope.streams = [];
$scope.view_port = {'x': 0,
'y': 0,
'width': 0,
'height': 0};
$scope.null_controller = new fsm.FSMController($scope, null_fsm.Start, null);
$scope.hotkeys_controller = new fsm.FSMController($scope, hotkeys.Start, $scope.null_controller);
$scope.view_controller = new fsm.FSMController($scope, view.Start, $scope.hotkeys_controller);
$scope.device_detail_controller = new fsm.FSMController($scope, device_detail_fsm.Start, $scope.view_controller);
$scope.move_controller = new fsm.FSMController($scope, move.Start, $scope.device_detail_controller);
$scope.link_controller = new fsm.FSMController($scope, link.Start, $scope.move_controller);
$scope.stream_controller = new fsm.FSMController($scope, stream_fsm.Start, $scope.link_controller);
$scope.group_controller = new fsm.FSMController($scope, group.Start, $scope.stream_controller);
$scope.rack_controller = new fsm.FSMController($scope, rack_fsm.Disable, $scope.group_controller);
$scope.site_controller = new fsm.FSMController($scope, site_fsm.Disable, $scope.rack_controller);
$scope.buttons_controller = new fsm.FSMController($scope, buttons.Start, $scope.site_controller);
$scope.time_controller = new fsm.FSMController($scope, time.Start, $scope.buttons_controller);
$scope.app_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.time_controller);
//App Toolbox Setup
$scope.app_toolbox = new models.ToolBox(0, 'Application', 'app', 10, 200, 150, $scope.graph.height - 200 - 100);
$scope.app_toolbox.spacing = 150;
$scope.app_toolbox.enabled = false;
$scope.app_toolbox_controller.toolbox = $scope.app_toolbox;
$scope.app_toolbox_controller.dropped_action = function (selected_item) {
$scope.first_controller.handle_message("PasteProcess", new messages.PasteProcess(selected_item));
};
$scope.app_toolbox.items.push(new models.Application(0, 'BGP', 'process', 0, 0));
$scope.app_toolbox.items.push(new models.Application(0, 'OSPF', 'process', 0, 0));
$scope.app_toolbox.items.push(new models.Application(0, 'STP', 'process', 0, 0));
$scope.app_toolbox.items.push(new models.Application(0, 'Zero Pipeline', 'process', 0, 0));
for(i = 0; i < $scope.app_toolbox.items.length; i++) {
$scope.app_toolbox.items[i].icon = true;
}
$scope.inventory_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.app_toolbox_controller);
//Inventory Toolbox Setup
$scope.inventory_toolbox = new models.ToolBox(0, 'Inventory', 'device', 10, 200, 150, $scope.graph.height - 200 - 100);
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router6', 0, 0, 'router'));
$scope.inventory_toolbox.items.push(new models.Device(0, 'Switch6', 0, 0, 'switch'));
$scope.inventory_toolbox.items.push(new models.Device(0, 'Host6', 0, 0, 'host'));
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router7', 0, 0, 'router'));
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router8', 0, 0, 'router'));
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router9', 0, 0, 'router'));
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router10', 0, 0, 'router'));
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router11', 0, 0, 'router'));
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router12', 0, 0, 'router'));
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router13', 0, 0, 'router'));
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router14', 0, 0, 'router'));
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router15', 0, 0, 'router'));
$scope.inventory_toolbox.items.push(new models.Device(0, 'Router16', 0, 0, 'router'));
$scope.inventory_toolbox.spacing = 150;
$scope.inventory_toolbox.enabled = true;
$scope.inventory_toolbox_controller.toolbox = $scope.inventory_toolbox;
$scope.inventory_toolbox_controller.remove_on_drop = true;
$scope.inventory_toolbox_controller.dropped_action = function (selected_item) {
$scope.first_controller.handle_message("PasteDevice", new messages.PasteDevice(selected_item));
};
for(i = 0; i < $scope.inventory_toolbox.items.length; i++) {
$scope.inventory_toolbox.items[i].icon = true;
}
//End Inventory Toolbox Setup
$scope.rack_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.inventory_toolbox_controller);
//Rack Toolbox Setup
$scope.rack_toolbox = new models.ToolBox(0, 'Rack', 'rack', 10, 200, 150, $scope.graph.height - 200 - 100);
$scope.rack_toolbox.items.push(new models.Group(0, 'Rack3', 'rack', 0, 0, 200, 1000, 'false'));
$scope.rack_toolbox.spacing = 200;
$scope.rack_toolbox.enabled = false;
$scope.rack_toolbox_controller.remove_on_drop = false;
$scope.rack_toolbox_controller.toolbox = $scope.rack_toolbox;
$scope.rack_toolbox_controller.dropped_action = function (selected_item) {
$scope.first_controller.handle_message("PasteRack", new messages.PasteRack(selected_item));
};
for(i = 0; i < $scope.rack_toolbox.items.length; i++) {
$scope.rack_toolbox.items[i].icon = true;
$scope.rack_toolbox.items[i].selected = false;
}
//End Rack Toolbox Setup
$scope.site_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.rack_toolbox_controller);
//Site Toolbox Setup
$scope.site_toolbox = new models.ToolBox(0, 'Sites', 'sites', 10, 200, 150, $scope.graph.height - 200 - 100);
$scope.site_toolbox.items.push(new models.Group(0, 'Site3', 'site', 0, 0, 1000, 1000, 'false'));
$scope.site_toolbox.spacing = 200;
$scope.site_toolbox.enabled = false;
$scope.site_toolbox_controller.remove_on_drop = false;
$scope.site_toolbox_controller.toolbox = $scope.site_toolbox;
$scope.site_toolbox_controller.dropped_action = function (selected_item) {
$scope.first_controller.handle_message("PasteSite", new messages.PasteSite(selected_item));
};
for(i = 0; i < $scope.site_toolbox.items.length; i++) {
$scope.site_toolbox.items[i].icon = true;
$scope.site_toolbox.items[i].selected = false;
}
//End Site Toolbox Setup
$scope.mode_controller = new fsm.FSMController($scope, mode_fsm.Start, $scope.site_toolbox_controller);
$scope.first_controller = $scope.mode_controller;
var getMouseEventResult = function (mouseEvent) {
return "(" + mouseEvent.x + ", " + mouseEvent.y + ")";
};
@ -109,6 +208,10 @@ var NetworkUIController = function($scope, $document, $location, $window) {
$scope.updateScaledXY = function() {
$scope.scaledX = ($scope.mouseX - $scope.panX) / $scope.current_scale;
$scope.scaledY = ($scope.mouseY - $scope.panY) / $scope.current_scale;
$scope.view_port.x = - $scope.panX / $scope.current_scale;
$scope.view_port.y = - $scope.panY / $scope.current_scale;
$scope.view_port.width = $scope.graph.width / $scope.current_scale;
$scope.view_port.height = $scope.graph.height / $scope.current_scale;
};
$scope.updatePanAndScale = function() {
@ -488,6 +591,8 @@ var NetworkUIController = function($scope, $document, $location, $window) {
new models.Button("CONFIGURE", 520, 10, 90, 30, $scope.onConfigureButton)
];
$scope.buttons = [];
var LAYERS_X = 160;
$scope.layers = [
@ -518,7 +623,8 @@ var NetworkUIController = function($scope, $document, $location, $window) {
new models.Button("Router", STENCIL_X, STENCIL_Y + STENCIL_SPACING * 1, 70, 30, function () {$scope.first_controller.handle_message("NewDevice", new messages.NewDevice("router"));}),
new models.Button("Host", STENCIL_X, STENCIL_Y + STENCIL_SPACING * 2, 70, 30, function () {$scope.first_controller.handle_message("NewDevice", new messages.NewDevice("host"));}),
new models.Button("Link", STENCIL_X, STENCIL_Y + STENCIL_SPACING * 3, 70, 30, function () { $scope.first_controller.handle_message("NewLink");}),
new models.Button("Group", STENCIL_X, STENCIL_Y + STENCIL_SPACING * 4, 70, 30, function () { $scope.first_controller.handle_message("NewGroup");}),
new models.Button("Group", STENCIL_X, STENCIL_Y + STENCIL_SPACING * 4, 70, 30, function () { $scope.first_controller.handle_message("NewGroup", new messages.NewGroup("group"));}),
new models.Button("Site", STENCIL_X, STENCIL_Y + STENCIL_SPACING * 5, 70, 30, function () { $scope.first_controller.handle_message("NewGroup", new messages.NewGroup("site"));}),
];
$scope.all_buttons = [];
@ -663,6 +769,23 @@ var NetworkUIController = function($scope, $document, $location, $window) {
$scope.devices.push(device);
};
$scope.onGroupCreate = function(data) {
$scope.create_group(data);
};
$scope.create_group = function(data) {
var group = new models.Group(data.id,
data.name,
data.type,
data.x1,
data.y1,
data.x2,
data.y2,
false);
$scope.group_id_seq = util.natural_numbers(data.id);
$scope.groups.push(group);
};
$scope.forDevice = function(device_id, data, fn) {
var i = 0;
for (i = 0; i < $scope.devices.length; i++) {
@ -1088,6 +1211,7 @@ var NetworkUIController = function($scope, $document, $location, $window) {
}
new_group = new models.Group(group.id,
group.name,
group.type,
group.x1,
group.y1,
group.x2,
@ -1244,6 +1368,26 @@ var NetworkUIController = function($scope, $document, $location, $window) {
$scope.layers[i].x = $scope.graph.width - 140;
}
};
$scope.update_offsets = function () {
var i = 0;
var streams = $scope.streams;
var map = new Map();
var stream = null;
var key = null;
for (i = 0; i < streams.length; i++) {
stream = streams[i];
key = "" + stream.from_device.id + "_" + stream.to_device.id;
map.set(key, 0);
}
for (i = 0; i < streams.length; i++) {
stream = streams[i];
key = "" + stream.from_device.id + "_" + stream.to_device.id;
stream.offset = map.get(key);
map.set(key, stream.offset + 1);
}
};
};
exports.NetworkUIController = NetworkUIController;

View File

@ -0,0 +1,66 @@
//console.log = function () { };
var angular = require('angular');
var NetworkWidgetsController = require('./network.widgets.controller.js');
var cursor = require('./cursor.directive.js');
var touch = require('./touch.directive.js');
var router = require('./router.directive.js');
var switchd = require('./switch.directive.js');
var host = require('./host.directive.js');
var link = require('./link.directive.js');
var stream = require('./stream.directive.js');
var rack = require('./rack.directive.js');
var rackIcon = require('./rack.icon.directive.js');
var group = require('./group.directive.js');
var site = require('./site.directive.js');
var siteIcon = require('./site.icon.directive.js');
var process = require('./process.directive.js');
var configuration = require('./configuration.directive.js');
var map = require('./map.directive.js');
var deviceDetail = require('./device.detail.directive.js');
var defaultd = require('./default.directive.js');
var quadrants = require('./quadrants.directive.js');
var stencil = require('./stencil.directive.js');
var layer = require('./layer.directive.js');
var button = require('./button.directive.js');
var inventoryToolbox = require('./inventory.toolbox.directive.js');
var inventoryToolboxClipPath = require('./inventory.toolbox.clip.path.directive.js');
var statusLight = require('./status.light.directive.js');
var taskStatus = require('./task.status.directive.js');
var debug = require('./debug.directive.js');
var awxNetworkWidgets = require('./network.widgets.directive.js');
var networkWidgets = angular.module('networkWidgets', [
'monospaced.mousewheel',
'ngTouch'
])
.controller('NetworkWidgetsController', NetworkWidgetsController.NetworkWidgetsController)
.directive('awxNetCursor', cursor.cursor)
.directive('awxNetTouch', touch.touch)
.directive('awxNetDebug', debug.debug)
.directive('awxNetRouter', router.router)
.directive('awxNetSwitch', switchd.switchd)
.directive('awxNetHost', host.host)
.directive('awxNetLink', link.link)
.directive('awxNetStream', stream.stream)
.directive('awxNetRack', rack.rack)
.directive('awxNetGroup', group.group)
.directive('awxNetSite', site.site)
.directive('awxNetSiteIcon', siteIcon.siteIcon)
.directive('awxNetRackIcon', rackIcon.rackIcon)
.directive('awxNetProcess', process.process)
.directive('awxNetConfiguration', configuration.configuration)
.directive('awxNetMap', map.map)
.directive('awxNetDeviceDetail', deviceDetail.deviceDetail)
.directive('awxNetDefault', defaultd.defaultd)
.directive('awxNetQuadrants', quadrants.quadrants)
.directive('awxNetStencil', stencil.stencil)
.directive('awxNetLayer', layer.layer)
.directive('awxNetButton', button.button)
.directive('awxNetInventoryToolbox', inventoryToolbox.inventoryToolbox)
.directive('awxNetInventoryToolboxClipPath', inventoryToolboxClipPath.inventoryToolboxClipPath)
.directive('awxNetStatusLight', statusLight.statusLight)
.directive('awxNetTaskStatus', taskStatus.taskStatus)
.directive('awxNetworkWidgets', awxNetworkWidgets.awxNetworkWidgets);
exports.networkWidgets = networkWidgets;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
function awxNetworkWidgets () {
return { restrict: 'E', templateUrl: '/static/network_ui/widgets/network_widgets.html' };
}
exports.awxNetworkWidgets = awxNetworkWidgets;

View File

@ -0,0 +1,5 @@
function process () {
return { restrict: 'A', templateUrl: '/static/network_ui/widgets/process.html' };
}
exports.process = process;

View File

@ -0,0 +1,487 @@
var inherits = require('inherits');
var fsm = require('./fsm.js');
var models = require('./models.js');
var messages = require('./messages.js');
function _State () {
}
inherits(_State, fsm._State);
function _Ready () {
this.name = 'Ready';
}
inherits(_Ready, _State);
var Ready = new _Ready();
exports.Ready = Ready;
function _Disable () {
this.name = 'Disable';
}
inherits(_Disable, _State);
var Disable = new _Disable();
exports.Disable = Disable;
function _Start () {
this.name = 'Start';
}
inherits(_Start, _State);
var Start = new _Start();
exports.Start = Start;
function _Selected1 () {
this.name = 'Selected1';
}
inherits(_Selected1, _State);
var Selected1 = new _Selected1();
exports.Selected1 = Selected1;
function _Selected2 () {
this.name = 'Selected2';
}
inherits(_Selected2, _State);
var Selected2 = new _Selected2();
exports.Selected2 = Selected2;
function _Selected3 () {
this.name = 'Selected3';
}
inherits(_Selected3, _State);
var Selected3 = new _Selected3();
exports.Selected3 = Selected3;
function _EditLabel () {
this.name = 'EditLabel';
}
inherits(_EditLabel, _State);
var EditLabel = new _EditLabel();
exports.EditLabel = EditLabel;
function _Move () {
this.name = 'Move';
}
inherits(_Move, _State);
var Move = new _Move();
exports.Move = Move;
_Start.prototype.start = function (controller) {
controller.changeState(Ready);
};
_Start.prototype.start.transitions = ['Ready'];
_Ready.prototype.onPasteRack = function (controller, msg_type, message) {
var scope = controller.scope;
var device = null;
var intf = null;
var process = null;
var link = null;
var i = 0;
var j = 0;
var top_left_x, top_left_y;
var device_map = {};
scope.hide_groups = false;
scope.pressedX = scope.mouseX;
scope.pressedY = scope.mouseY;
scope.pressedScaledX = scope.scaledX;
scope.pressedScaledY = scope.scaledY;
top_left_x = scope.scaledX - message.group.x2/2;
top_left_y = scope.scaledY - message.group.y2/2;
var group = new models.Group(controller.scope.group_id_seq(),
message.group.name,
message.group.type,
top_left_x,
top_left_y,
top_left_x + message.group.x2,
top_left_y + message.group.y2,
false);
scope.send_control_message(new messages.GroupCreate(scope.client_id,
group.id,
group.x1,
group.y1,
group.x2,
group.y2,
group.name,
group.type));
scope.groups.push(group);
for(i=0; i<message.group.devices.length;i++) {
device = new models.Device(controller.scope.device_id_seq(),
message.group.devices[i].name,
top_left_x + message.group.devices[i].x,
top_left_y + message.group.devices[i].y,
message.group.devices[i].type);
device_map[message.group.devices[i].id] = device;
device.interface_map = {};
scope.devices.push(device);
group.devices.push(device);
scope.send_control_message(new messages.DeviceCreate(scope.client_id,
device.id,
device.x,
device.y,
device.name,
device.type));
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;
device.interfaces.push(intf);
device.interface_map[intf.id] = intf;
}
for (j=0; j < message.group.devices[i].processes.length; j++) {
process = new models.Application(message.group.devices[i].processes[j].id,
message.group.devices[i].processes[j].name,
message.group.devices[i].processes[j].type, 0, 0);
device.processes.push(process);
}
}
for(i=0; i<message.group.links.length;i++) {
link = new models.Link(controller.scope.link_id_seq(),
device_map[message.group.links[i].from_device.id],
device_map[message.group.links[i].to_device.id],
device_map[message.group.links[i].from_device.id].interface_map[message.group.links[i].from_interface.id],
device_map[message.group.links[i].to_device.id].interface_map[message.group.links[i].to_interface.id]);
link.name = message.group.links[i].name;
device_map[message.group.links[i].from_device.id].interface_map[message.group.links[i].from_interface.id].link = link;
device_map[message.group.links[i].to_device.id].interface_map[message.group.links[i].to_interface.id].link = link;
device_map[message.group.links[i].from_device.id].interface_map[message.group.links[i].from_interface.id].dot();
device_map[message.group.links[i].to_device.id].interface_map[message.group.links[i].to_interface.id].dot();
scope.links.push(link);
}
};
_Selected1.prototype.onMouseUp = function (controller) {
controller.changeState(Selected2);
};
_Selected1.prototype.onMouseUp.transitions = ['Selected2'];
_Selected1.prototype.onMouseMove = function (controller) {
controller.changeState(Move);
};
_Selected1.prototype.onMouseMove.transitions = ['Move'];
_Selected2.prototype.onPasteRack = function (controller, msg_type, message) {
controller.changeState(Ready);
controller.handle_message(msg_type, message);
};
_Selected2.prototype.onCopySelected = function (controller) {
var groups = controller.scope.selected_groups;
var group_copy = null;
var group = null;
var devices = null;
var device_copy = null;
var process_copy = null;
var interface_copy = null;
var link_copy = null;
var device_map = {};
var i = 0;
var j = 0;
var k = 0;
for(i=0; i < groups.length; i++) {
group = groups[i];
group_copy = new models.Group(0,
group.name,
group.type,
0,
0,
group.right_extent() - group.left_extent(),
group.bottom_extent() - group.top_extent(),
false);
group_copy.icon = true;
devices = group.devices;
for(j=0; j < devices.length; j++) {
device_copy = new models.Device(devices[j].id,
devices[j].name,
devices[j].x - group.left_extent(),
devices[j].y - group.top_extent(),
devices[j].type);
device_map[device_copy.id] = device_copy;
device_copy.icon = true;
device_copy.interface_map = {};
for(k=0; k < devices[j].processes.length; k++) {
process_copy = new models.Application(0, devices[j].processes[k].name, devices[j].processes[k].name, 0, 0);
device_copy.processes.push(process_copy);
}
for(k=0; k < devices[j].interfaces.length; k++) {
interface_copy = new models.Interface(devices[j].interfaces[k].id, devices[j].interfaces[k].name);
device_copy.interfaces.push(interface_copy);
device_copy.interface_map[interface_copy.id] = interface_copy;
}
group_copy.devices.push(device_copy);
}
group_copy.link_ids = [];
for(j=0; j < devices.length; j++) {
for(k=0; k < devices[j].interfaces.length; k++) {
if (devices[j].interfaces[k].link !== null) {
if ((devices.indexOf(devices[j].interfaces[k].remote_interface().device) !== -1) &&
(group_copy.link_ids.indexOf(devices[j].interfaces[k].link.id) === -1)) {
link_copy = new models.Link(devices[j].interfaces[k].link.id,
device_map[devices[j].interfaces[k].link.from_device.id],
device_map[devices[j].interfaces[k].link.to_device.id],
device_map[devices[j].interfaces[k].link.from_device.id].interface_map[devices[j].interfaces[k].link.from_interface.id],
device_map[devices[j].interfaces[k].link.to_device.id].interface_map[devices[j].interfaces[k].link.to_interface.id]);
link_copy.name = devices[j].interfaces[k].link.name;
group_copy.links.push(link_copy);
group_copy.link_ids.push(link_copy.id);
}
}
}
}
controller.scope.rack_toolbox.items.push(group_copy);
}
};
_Selected2.prototype.onKeyDown = function (controller, msg_type, $event) {
//controller.changeState(Ready);
controller.next_controller.handle_message(msg_type, $event);
};
_Selected2.prototype.onKeyDown.transitions = ['Ready'];
_Selected2.prototype.onMouseDown = function (controller, msg_type, $event) {
controller.scope.pressedScaledX = controller.scope.scaledX;
controller.scope.pressedScaledY = controller.scope.scaledY;
var groups = controller.scope.selected_groups;
var i = 0;
var selected = false;
controller.scope.selected_groups = [];
for (i = 0; i < groups.length; i++) {
if (groups[i].type !== "rack") {
continue;
}
if (groups[i].is_icon_selected(controller.scope.scaledX, controller.scope.scaledY)) {
groups[i].selected = true;
selected = true;
controller.scope.selected_groups.push(groups[i]);
}
}
if (selected) {
controller.changeState(Selected3);
} else {
for (i = 0; i < groups.length; i++) {
groups[i].selected = false;
}
controller.changeState(Ready);
controller.handle_message(msg_type, $event);
}
};
_Selected2.prototype.onMouseDown.transitions = ['Selected3', 'Ready'];
_Selected3.prototype.onMouseUp = function (controller) {
controller.changeState(EditLabel);
};
_Selected3.prototype.onMouseUp.transitions = ['EditLabel'];
_Selected3.prototype.onMouseMove = function (controller) {
controller.changeState(Move);
};
_Selected3.prototype.onMouseMove.transitions = ['Move'];
_EditLabel.prototype.start = function (controller) {
controller.scope.selected_groups[0].edit_label = true;
};
_EditLabel.prototype.end = function (controller) {
controller.scope.selected_groups[0].edit_label = false;
};
_EditLabel.prototype.onMouseDown = function (controller, msg_type, $event) {
controller.changeState(Ready);
controller.handle_message(msg_type, $event);
};
_EditLabel.prototype.onMouseDown.transitions = ['Ready'];
_EditLabel.prototype.onKeyDown = function (controller, msg_type, $event) {
//Key codes found here:
//https://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes
var item = controller.scope.selected_groups[0];
var previous_name = item.name;
if ($event.keyCode === 8 || $event.keyCode === 46) { //Delete
item.name = item.name.slice(0, -1);
} else if ($event.keyCode >= 48 && $event.keyCode <=90) { //Alphanumeric
item.name += $event.key;
} else if ($event.keyCode >= 186 && $event.keyCode <=222) { //Punctuation
item.name += $event.key;
} else if ($event.keyCode === 13) { //Enter
controller.changeState(Selected2);
} else if ($event.keyCode === 32) { //Space
item.name += " ";
} else {
console.log($event.keyCode);
}
controller.scope.send_control_message(new messages.GroupLabelEdit(controller.scope.client_id,
item.id,
item.name,
previous_name));
};
_EditLabel.prototype.onKeyDown.transitions = ['Selected2'];
_Ready.prototype.onMouseDown = function (controller, msg_type, $event) {
controller.scope.pressedScaledX = controller.scope.scaledX;
controller.scope.pressedScaledY = controller.scope.scaledY;
var groups = controller.scope.groups;
var i = 0;
var selected = false;
controller.scope.clear_selections();
for (i = 0; i < groups.length; i++) {
if (groups[i].type !== "rack") {
continue;
}
if (groups[i].is_icon_selected(controller.scope.scaledX, controller.scope.scaledY)) {
groups[i].selected = true;
selected = true;
controller.scope.selected_groups.push(groups[i]);
}
}
if (selected) {
controller.changeState(Selected1);
} else {
controller.next_controller.handle_message(msg_type, $event);
}
};
_Ready.prototype.onMouseDown.transitions = ['Selected1'];
_Move.prototype.start = function (controller) {
var groups = controller.scope.selected_groups;
var i = 0;
for (i = 0; i < groups.length; i++) {
groups[i].moving = true;
}
};
_Move.prototype.end = function (controller) {
var groups = controller.scope.selected_groups;
var i = 0;
var j = 0;
for (i = 0; i < groups.length; i++) {
for(j = 0; j < groups[i].devices.length; j++) {
groups[i].devices[j].selected = false;
}
}
for (i = 0; i < groups.length; i++) {
groups[i].moving = false;
}
};
_Move.prototype.onMouseUp = function (controller) {
controller.changeState(Selected2);
};
_Move.prototype.onMouseUp.transitions = ['Selected2'];
_Move.prototype.onMouseMove = function (controller) {
var groups = controller.scope.selected_groups;
var devices = null;
var diffX = controller.scope.scaledX - controller.scope.pressedScaledX;
var diffY = controller.scope.scaledY - controller.scope.pressedScaledY;
var i = 0;
var j = 0;
var k = 0;
var previous_x1, previous_y1, previous_x2, previous_y2, previous_x, previous_y;
for (i = 0; i < groups.length; i++) {
previous_x1 = groups[i].x1;
previous_y1 = groups[i].y1;
previous_x2 = groups[i].x2;
previous_y2 = groups[i].y2;
groups[i].x1 = groups[i].x1 + diffX;
groups[i].y1 = groups[i].y1 + diffY;
groups[i].x2 = groups[i].x2 + diffX;
groups[i].y2 = groups[i].y2 + diffY;
controller.scope.send_control_message(new messages.GroupMove(controller.scope.client_id,
groups[i].id,
groups[i].x1,
groups[i].y1,
groups[i].x2,
groups[i].y2,
previous_x1,
previous_y1,
previous_x2,
previous_y2));
devices = groups[i].devices;
for (j = 0; j < devices.length; j++) {
previous_x = devices[j].x;
previous_y = devices[j].y;
devices[j].x = devices[j].x + diffX;
devices[j].y = devices[j].y + diffY;
for (k = 0; k < devices[j].interfaces.length; k++) {
devices[j].interfaces[k].dot();
if (devices[j].interfaces[k].link !== null) {
devices[j].interfaces[k].link.to_interface.dot();
devices[j].interfaces[k].link.from_interface.dot();
}
}
controller.scope.send_control_message(new messages.DeviceMove(controller.scope.client_id,
devices[j].id,
devices[j].x,
devices[j].y,
previous_x,
previous_y));
}
}
controller.scope.pressedScaledX = controller.scope.scaledX;
controller.scope.pressedScaledY = controller.scope.scaledY;
};
_Move.prototype.onTouchMove = _Move.prototype.onMouseMove;

View File

@ -0,0 +1,5 @@
function rackIcon () {
return { restrict: 'A', templateUrl: '/static/network_ui/widgets/rack_icon.html' };
}
exports.rackIcon = rackIcon;

View File

@ -0,0 +1,5 @@
function site () {
return { restrict: 'A', templateUrl: '/static/network_ui/widgets/site.html' };
}
exports.site = site;

View File

@ -0,0 +1,567 @@
var inherits = require('inherits');
var fsm = require('./fsm.js');
var models = require('./models.js');
var messages = require('./messages.js');
function _State () {
}
inherits(_State, fsm._State);
function _Ready () {
this.name = 'Ready';
}
inherits(_Ready, _State);
var Ready = new _Ready();
exports.Ready = Ready;
function _Disable () {
this.name = 'Disable';
}
inherits(_Disable, _State);
var Disable = new _Disable();
exports.Disable = Disable;
function _Start () {
this.name = 'Start';
}
inherits(_Start, _State);
var Start = new _Start();
exports.Start = Start;
function _Selected1 () {
this.name = 'Selected1';
}
inherits(_Selected1, _State);
var Selected1 = new _Selected1();
exports.Selected1 = Selected1;
function _Selected2 () {
this.name = 'Selected2';
}
inherits(_Selected2, _State);
var Selected2 = new _Selected2();
exports.Selected2 = Selected2;
function _Selected3 () {
this.name = 'Selected3';
}
inherits(_Selected3, _State);
var Selected3 = new _Selected3();
exports.Selected3 = Selected3;
function _EditLabel () {
this.name = 'EditLabel';
}
inherits(_EditLabel, _State);
var EditLabel = new _EditLabel();
exports.EditLabel = EditLabel;
function _Move () {
this.name = 'Move';
}
inherits(_Move, _State);
var Move = new _Move();
exports.Move = Move;
_Start.prototype.start = function (controller) {
controller.changeState(Ready);
};
_Start.prototype.start.transitions = ['Ready'];
_Ready.prototype.onPasteSite = function (controller, msg_type, message) {
var scope = controller.scope;
var device = null;
var intf = null;
var process = null;
var link = null;
var stream = null;
var i = 0;
var j = 0;
var top_left_x, top_left_y;
var device_map = {};
var inner_group = null;
scope.hide_groups = false;
scope.pressedX = scope.mouseX;
scope.pressedY = scope.mouseY;
scope.pressedScaledX = scope.scaledX;
scope.pressedScaledY = scope.scaledY;
top_left_x = scope.scaledX - message.group.x2/2;
top_left_y = scope.scaledY - message.group.y2/2;
var group = new models.Group(controller.scope.group_id_seq(),
message.group.name,
message.group.type,
top_left_x,
top_left_y,
top_left_x + message.group.x2,
top_left_y + message.group.y2,
false);
scope.send_control_message(new messages.GroupCreate(scope.client_id,
group.id,
group.x1,
group.y1,
group.x2,
group.y2,
group.name,
group.type));
scope.groups.push(group);
for(i=0; i<message.group.devices.length;i++) {
device = new models.Device(controller.scope.device_id_seq(),
message.group.devices[i].name,
top_left_x + message.group.devices[i].x,
top_left_y + message.group.devices[i].y,
message.group.devices[i].type);
device_map[message.group.devices[i].id] = device;
device.interface_map = {};
scope.devices.push(device);
group.devices.push(device);
scope.send_control_message(new messages.DeviceCreate(scope.client_id,
device.id,
device.x,
device.y,
device.name,
device.type));
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;
device.interfaces.push(intf);
device.interface_map[intf.id] = intf;
}
for (j=0; j < message.group.devices[i].processes.length; j++) {
process = new models.Application(message.group.devices[i].processes[j].id,
message.group.devices[i].processes[j].name,
message.group.devices[i].processes[j].type, 0, 0);
device.processes.push(process);
}
}
for(i=0; i<message.group.links.length;i++) {
link = new models.Link(controller.scope.link_id_seq(),
device_map[message.group.links[i].from_device.id],
device_map[message.group.links[i].to_device.id],
device_map[message.group.links[i].from_device.id].interface_map[message.group.links[i].from_interface.id],
device_map[message.group.links[i].to_device.id].interface_map[message.group.links[i].to_interface.id]);
link.name = message.group.links[i].name;
device_map[message.group.links[i].from_device.id].interface_map[message.group.links[i].from_interface.id].link = link;
device_map[message.group.links[i].to_device.id].interface_map[message.group.links[i].to_interface.id].link = link;
device_map[message.group.links[i].from_device.id].interface_map[message.group.links[i].from_interface.id].dot();
device_map[message.group.links[i].to_device.id].interface_map[message.group.links[i].to_interface.id].dot();
scope.links.push(link);
}
for(i=0; i<message.group.streams.length;i++) {
stream = new models.Stream(controller.scope.stream_id_seq(),
device_map[message.group.streams[i].from_device.id],
device_map[message.group.streams[i].to_device.id],
message.group.streams[i].label);
stream.name = message.group.streams[i].name;
scope.streams.push(stream);
}
for(i=0; i<message.group.groups.length;i++) {
inner_group = new models.Group(controller.scope.group_id_seq(),
message.group.groups[i].name,
message.group.groups[i].type,
top_left_x + message.group.groups[i].x1,
top_left_y + message.group.groups[i].y1,
top_left_x + message.group.groups[i].x2,
top_left_y + message.group.groups[i].y2,
false);
scope.groups.push(inner_group);
group.groups.push(inner_group);
}
for(i=0; i< group.groups.length; i++) {
group.groups[i].update_membership(scope.devices, scope.groups);
}
};
_Selected1.prototype.onMouseUp = function (controller) {
controller.changeState(Selected2);
};
_Selected1.prototype.onMouseUp.transitions = ['Selected2'];
_Selected1.prototype.onMouseMove = function (controller) {
controller.changeState(Move);
};
_Selected1.prototype.onMouseMove.transitions = ['Move'];
_Selected2.prototype.onPasteSite = function (controller, msg_type, message) {
controller.changeState(Ready);
controller.handle_message(msg_type, message);
};
_Selected2.prototype.onCopySelected = function (controller) {
var groups = controller.scope.selected_groups;
var group_copy = null;
var group = null;
var inner_group = null;
var devices = null;
var device_copy = null;
var process_copy = null;
var interface_copy = null;
var link_copy = null;
var device_map = {};
var streams = controller.scope.streams;
var stream;
var stream_copy;
var i = 0;
var j = 0;
var k = 0;
for(i=0; i < groups.length; i++) {
group = groups[i];
group_copy = new models.Group(0,
group.name,
group.type,
0,
0,
group.right_extent() - group.left_extent(),
group.bottom_extent() - group.top_extent(),
false);
group_copy.icon = true;
devices = group.devices;
for(j=0; j < devices.length; j++) {
device_copy = new models.Device(devices[j].id,
devices[j].name,
devices[j].x - group.left_extent(),
devices[j].y - group.top_extent(),
devices[j].type);
device_map[device_copy.id] = device_copy;
device_copy.icon = true;
device_copy.interface_map = {};
for(k=0; k < devices[j].processes.length; k++) {
process_copy = new models.Application(0, devices[j].processes[k].name, devices[j].processes[k].name, 0, 0);
device_copy.processes.push(process_copy);
}
for(k=0; k < devices[j].interfaces.length; k++) {
interface_copy = new models.Interface(devices[j].interfaces[k].id, devices[j].interfaces[k].name);
device_copy.interfaces.push(interface_copy);
device_copy.interface_map[interface_copy.id] = interface_copy;
}
group_copy.devices.push(device_copy);
}
group_copy.link_ids = [];
for(j=0; j < devices.length; j++) {
for(k=0; k < devices[j].interfaces.length; k++) {
if (devices[j].interfaces[k].link !== null) {
if ((devices.indexOf(devices[j].interfaces[k].remote_interface().device) !== -1) &&
(group_copy.link_ids.indexOf(devices[j].interfaces[k].link.id) === -1)) {
link_copy = new models.Link(devices[j].interfaces[k].link.id,
device_map[devices[j].interfaces[k].link.from_device.id],
device_map[devices[j].interfaces[k].link.to_device.id],
device_map[devices[j].interfaces[k].link.from_device.id].interface_map[devices[j].interfaces[k].link.from_interface.id],
device_map[devices[j].interfaces[k].link.to_device.id].interface_map[devices[j].interfaces[k].link.to_interface.id]);
link_copy.name = devices[j].interfaces[k].link.name;
group_copy.links.push(link_copy);
group_copy.link_ids.push(link_copy.id);
}
}
}
}
group_copy.stream_ids = [];
for (j=0; j<streams.length;j++) {
stream = streams[j];
if ((devices.indexOf(stream.to_device) !== -1) &&
(devices.indexOf(stream.from_device) !== -1)) {
stream_copy = new models.Stream(0, device_map[stream.from_device.id], device_map[stream.to_device.id], stream.label);
group_copy.streams.push(stream_copy);
}
}
for (j=0; j<group.groups.length;j++) {
inner_group = new models.Group(0,
group.groups[j].name,
group.groups[j].type,
group.groups[j].left_extent() - group.left_extent(),
group.groups[j].top_extent() - group.top_extent(),
group.groups[j].right_extent() - group.left_extent(),
group.groups[j].bottom_extent() - group.top_extent(),
false);
group_copy.groups.push(inner_group);
}
controller.scope.site_toolbox.items.push(group_copy);
}
};
_Selected2.prototype.onKeyDown = function (controller, msg_type, $event) {
//controller.changeState(Ready);
controller.next_controller.handle_message(msg_type, $event);
};
_Selected2.prototype.onKeyDown.transitions = ['Ready'];
_Selected2.prototype.onMouseDown = function (controller, msg_type, $event) {
controller.scope.pressedScaledX = controller.scope.scaledX;
controller.scope.pressedScaledY = controller.scope.scaledY;
var groups = controller.scope.selected_groups;
var i = 0;
var selected = false;
controller.scope.selected_groups = [];
for (i = 0; i < groups.length; i++) {
if (groups[i].type !== "site") {
continue;
}
if (groups[i].is_icon_selected(controller.scope.scaledX, controller.scope.scaledY)) {
groups[i].selected = true;
selected = true;
controller.scope.selected_groups.push(groups[i]);
}
}
if (selected) {
controller.changeState(Selected3);
} else {
for (i = 0; i < groups.length; i++) {
groups[i].selected = false;
}
controller.changeState(Ready);
controller.handle_message(msg_type, $event);
}
};
_Selected2.prototype.onMouseDown.transitions = ['Selected3', 'Ready'];
_Selected3.prototype.onMouseUp = function (controller) {
controller.changeState(EditLabel);
};
_Selected3.prototype.onMouseUp.transitions = ['EditLabel'];
_Selected3.prototype.onMouseMove = function (controller) {
controller.changeState(Move);
};
_Selected3.prototype.onMouseMove.transitions = ['Move'];
_EditLabel.prototype.start = function (controller) {
controller.scope.selected_groups[0].edit_label = true;
};
_EditLabel.prototype.end = function (controller) {
controller.scope.selected_groups[0].edit_label = false;
};
_EditLabel.prototype.onMouseDown = function (controller, msg_type, $event) {
controller.changeState(Ready);
controller.handle_message(msg_type, $event);
};
_EditLabel.prototype.onMouseDown.transitions = ['Ready'];
_EditLabel.prototype.onKeyDown = function (controller, msg_type, $event) {
//Key codes found here:
//https://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes
var item = controller.scope.selected_groups[0];
var previous_name = item.name;
if ($event.keyCode === 8 || $event.keyCode === 46) { //Delete
item.name = item.name.slice(0, -1);
} else if ($event.keyCode >= 48 && $event.keyCode <=90) { //Alphanumeric
item.name += $event.key;
} else if ($event.keyCode >= 186 && $event.keyCode <=222) { //Punctuation
item.name += $event.key;
} else if ($event.keyCode === 13) { //Enter
controller.changeState(Selected2);
} else if ($event.keyCode === 32) { //Space
item.name += " ";
} else {
console.log($event.keyCode);
}
controller.scope.send_control_message(new messages.GroupLabelEdit(controller.scope.client_id,
item.id,
item.name,
previous_name));
};
_EditLabel.prototype.onKeyDown.transitions = ['Selected2'];
_Ready.prototype.onMouseDown = function (controller, msg_type, $event) {
controller.scope.pressedScaledX = controller.scope.scaledX;
controller.scope.pressedScaledY = controller.scope.scaledY;
var groups = controller.scope.groups;
var i = 0;
var selected = false;
controller.scope.clear_selections();
for (i = 0; i < groups.length; i++) {
if (groups[i].type !== "site") {
continue;
}
if (groups[i].is_icon_selected(controller.scope.scaledX, controller.scope.scaledY)) {
groups[i].selected = true;
selected = true;
controller.scope.selected_groups.push(groups[i]);
}
}
if (selected) {
controller.changeState(Selected1);
} else {
controller.next_controller.handle_message(msg_type, $event);
}
};
_Ready.prototype.onMouseDown.transitions = ['Selected1'];
_Move.prototype.start = function (controller) {
var groups = controller.scope.selected_groups;
var i = 0;
for (i = 0; i < groups.length; i++) {
groups[i].moving = true;
}
};
_Move.prototype.end = function (controller) {
var groups = controller.scope.selected_groups;
var i = 0;
var j = 0;
for (i = 0; i < groups.length; i++) {
for(j = 0; j < groups[i].devices.length; j++) {
groups[i].devices[j].selected = false;
}
}
for (i = 0; i < groups.length; i++) {
groups[i].moving = false;
}
};
_Move.prototype.onMouseUp = function (controller) {
controller.changeState(Selected2);
};
_Move.prototype.onMouseUp.transitions = ['Selected2'];
_Move.prototype.onMouseMove = function (controller) {
var groups = controller.scope.selected_groups;
var devices = null;
var diffX = controller.scope.scaledX - controller.scope.pressedScaledX;
var diffY = controller.scope.scaledY - controller.scope.pressedScaledY;
var i = 0;
var j = 0;
var k = 0;
var previous_x1, previous_y1, previous_x2, previous_y2, previous_x, previous_y;
for (i = 0; i < groups.length; i++) {
previous_x1 = groups[i].x1;
previous_y1 = groups[i].y1;
previous_x2 = groups[i].x2;
previous_y2 = groups[i].y2;
groups[i].x1 = groups[i].x1 + diffX;
groups[i].y1 = groups[i].y1 + diffY;
groups[i].x2 = groups[i].x2 + diffX;
groups[i].y2 = groups[i].y2 + diffY;
controller.scope.send_control_message(new messages.GroupMove(controller.scope.client_id,
groups[i].id,
groups[i].x1,
groups[i].y1,
groups[i].x2,
groups[i].y2,
previous_x1,
previous_y1,
previous_x2,
previous_y2));
devices = groups[i].devices;
for (j = 0; j < devices.length; j++) {
previous_x = devices[j].x;
previous_y = devices[j].y;
devices[j].x = devices[j].x + diffX;
devices[j].y = devices[j].y + diffY;
for (k = 0; k < devices[j].interfaces.length; k++) {
devices[j].interfaces[k].dot();
if (devices[j].interfaces[k].link !== null) {
devices[j].interfaces[k].link.to_interface.dot();
devices[j].interfaces[k].link.from_interface.dot();
}
}
controller.scope.send_control_message(new messages.DeviceMove(controller.scope.client_id,
devices[j].id,
devices[j].x,
devices[j].y,
previous_x,
previous_y));
}
for (j = 0; j < groups[i].groups.length; j++) {
previous_x1 = groups[i].groups[j].x1;
previous_y1 = groups[i].groups[j].y1;
previous_x2 = groups[i].groups[j].x2;
previous_y2 = groups[i].groups[j].y2;
groups[i].groups[j].x1 = groups[i].groups[j].x1 + diffX;
groups[i].groups[j].y1 = groups[i].groups[j].y1 + diffY;
groups[i].groups[j].x2 = groups[i].groups[j].x2 + diffX;
groups[i].groups[j].y2 = groups[i].groups[j].y2 + diffY;
controller.scope.send_control_message(new messages.GroupMove(controller.scope.client_id,
groups[i].groups[j].id,
groups[i].groups[j].x1,
groups[i].groups[j].y1,
groups[i].groups[j].x2,
groups[i].groups[j].y2,
previous_x1,
previous_y1,
previous_x2,
previous_y2));
}
}
controller.scope.pressedScaledX = controller.scope.scaledX;
controller.scope.pressedScaledY = controller.scope.scaledY;
};
_Move.prototype.onTouchMove = _Move.prototype.onMouseMove;

View File

@ -0,0 +1,5 @@
function siteIcon () {
return { restrict: 'A', templateUrl: '/static/network_ui/widgets/site_icon.html' };
}
exports.siteIcon = siteIcon;

View File

@ -0,0 +1,5 @@
function stream () {
return { restrict: 'A', templateUrl: '/static/network_ui/widgets/stream.html' };
}
exports.stream = stream;

View File

@ -0,0 +1,115 @@
var inherits = require('inherits');
var fsm = require('./fsm.js');
var models = require('./models.js');
var messages = require('./messages.js');
function _State () {
}
inherits(_State, fsm._State);
function _Ready () {
this.name = 'Ready';
}
inherits(_Ready, _State);
var Ready = new _Ready();
exports.Ready = Ready;
function _Start () {
this.name = 'Start';
}
inherits(_Start, _State);
var Start = new _Start();
exports.Start = Start;
function _Connected () {
this.name = 'Connected';
}
inherits(_Connected, _State);
var Connected = new _Connected();
exports.Connected = Connected;
function _Connecting () {
this.name = 'Connecting';
}
inherits(_Connecting, _State);
var Connecting = new _Connecting();
exports.Connecting = Connecting;
function _Selecting () {
this.name = 'Selecting';
}
inherits(_Selecting, _State);
var Selecting = new _Selecting();
exports.Selecting = Selecting;
_Ready.prototype.onNewStream = function (controller) {
controller.scope.clear_selections();
controller.changeState(Selecting);
};
_Ready.prototype.onNewStream.transitions = ['Selecting'];
_Start.prototype.start = function (controller) {
controller.changeState(Ready);
};
_Start.prototype.start.transitions = ['Ready'];
_Connected.prototype.start = function (controller) {
controller.scope.clear_selections();
controller.changeState(Ready);
};
_Connected.prototype.start.transitions = ['Ready'];
_Connecting.prototype.onMouseDown = function () {
};
_Connecting.prototype.onMouseUp = function (controller) {
var selected = controller.scope.select_items(false);
if (selected.last_selected_device !== null) {
controller.scope.new_stream.to_device = selected.last_selected_device;
controller.scope.send_control_message(new messages.StreamCreate(controller.scope.client_id,
controller.scope.new_stream.id,
controller.scope.new_stream.from_device.id,
controller.scope.new_stream.to_device.id),
'');
controller.scope.new_stream = null;
controller.scope.update_offsets();
controller.changeState(Connected);
} else {
var index = controller.scope.streams.indexOf(controller.scope.new_stream);
if (index !== -1) {
controller.scope.streams.splice(index, 1);
}
controller.scope.new_stream = null;
controller.changeState(Ready);
}
};
_Connecting.prototype.onMouseUp.transitions = ['Ready', 'Connected'];
_Selecting.prototype.onMouseDown = function () {
};
_Selecting.prototype.onMouseUp = function (controller) {
var selected = controller.scope.select_items(false);
if (selected.last_selected_device !== null) {
controller.scope.new_stream = new models.Stream(controller.scope.stream_id_seq(), selected.last_selected_device, null, '');
controller.scope.streams.push(controller.scope.new_stream);
controller.changeState(Connecting);
}
};
_Selecting.prototype.onMouseUp.transitions = ['Connecting'];

View File

@ -31,6 +31,7 @@
@button-text-pressed: #ffffff;
@green: #5CB85C;
@red: #D9534F;
@light-toolbox-background: #f6f6f6;
.NetworkUI {
background-color: @light-background;
@ -53,6 +54,12 @@
stroke-width: 1;
}
.NetworkUI--construction {
fill-opacity: 0;
stroke: @debug-copynot;
stroke-width: 1;
}
.NetworkUI__link--selected {
stroke: @selected-blue;
@ -227,6 +234,72 @@
stroke: none;
}
.NetworkUI__rack-text {
fill: @button-text;
font-family: 'Open Sans';
}
.NetworkUI__rack-text--selected {
font-family: 'Open Sans';
}
.NetworkUI__site {
fill: @widget-body;
stroke: @dark-widget-detail;
stroke-width: 2;
}
.NetworkUI__site--network {
fill: @dark-widget-detail;
stroke: @dark-widget-detail;
stroke-width: 2;
}
.NetworkUI__site-background {
fill: @light-background;
stroke: @light-background;
stroke-width: 2;
}
.NetworkUI__site--selected {
fill: @selected-blue;
stroke: @selected-blue;
stroke-width: 10;
}
.NetworkUI__site--remote-selected {
fill: @selected-mango;
stroke: @selected-mango;
stroke-width: 10;
}
.NetworkUI__site--selected-conflict {
fill: @selected-red;
stroke: @selected-red;
stroke-width: 10;
}
.NetworkUI__site line {
stroke: @dark-widget-detail;
stroke-width: 10;
}
.NetworkUI__site circle {
fill: @light-widget-detail;
stroke: none;
}
.NetworkUI__site-text {
fill: @button-text;
font-family: 'Open Sans';
}
.NetworkUI__site-text--selected {
font-family: 'Open Sans';
}
.NetworkUI__button {
fill: @button-body;
stroke: @button-outline;
@ -386,6 +459,52 @@
font-family: 'Open Sans';
}
.NetworkUI__device {
fill: @widget-body;
stroke: @dark-widget-detail;
stroke-width: 2;
}
.NetworkUI__device-background {
fill: @light-background;
stroke: @light-background;
stroke-width: 2;
}
.NetworkUI__device--selected {
fill: @selected-blue;
stroke: @selected-blue;
stroke-width: 10;
}
.NetworkUI__device--remote-selected {
fill: @selected-mango;
stroke: @selected-mango;
stroke-width: 10;
}
.NetworkUI__device--selected-conflict {
fill: @selected-red;
stroke: @selected-red;
stroke-width: 10;
}
.NetworkUI__device line {
stroke: @light-widget-detail;
stroke-width: 20;
}
.NetworkUI__device-text {
fill: @button-text;
font-family: 'Open Sans';
}
.NetworkUI__device-text--selected {
font-family: 'Open Sans';
}
.NetworkUI__status {
fill: @widget-body;
stroke: @dark-widget-detail;
@ -487,3 +606,92 @@
.NetworkUI__group-text--selected {
font-family: 'Open Sans';
}
.NetworkUI__location-text {
fill: @button-text;
font-family: 'Open Sans';
}
.NetworkUI__toolbox {
stroke: none;
fill: @light-toolbox-background;
}
.NetworkUI__toolbox-bezel {
stroke: @group;
stroke-width: 2;
fill: none;
}
.NetworkUI__process {
fill: @widget-body;
stroke: @dark-widget-detail;
stroke-width: 2;
}
.NetworkUI__process-background {
fill: @light-background;
stroke: @light-background;
stroke-width: 2;
}
.NetworkUI__process--selected {
fill: @selected-blue;
stroke: @selected-blue;
stroke-width: 10;
}
.NetworkUI__process--remote-selected {
fill: @selected-mango;
stroke: @selected-mango;
stroke-width: 10;
}
.NetworkUI__process--selected-conflict {
fill: @selected-red;
stroke: @selected-red;
stroke-width: 10;
}
.NetworkUI__process path {
fill: @widget-body;
stroke: @dark-widget-detail;
stroke-width: 2;
}
.NetworkUI__process-text {
fill: @button-text;
font-family: 'Open Sans';
}
.NetworkUI__process-text--selected {
font-family: 'Open Sans';
}
.NetworkUI__stream {
fill: none;
stroke: @dark-widget-detail;
}
.NetworkUI__stream-arrow {
fill: @dark-widget-detail;
stroke: @dark-widget-detail;
}
.NetworkUI__stream--selected {
fill: none;
stroke: @selected-blue;
stroke-width: 6;
}
.NetworkUI__stream-arrow--selected {
fill: @selected-blue;
stroke: @selected-blue;
}
.NetworkUI__stream-text {
fill: @button-text;
font-size: 8px;
font-family: 'Open Sans';
}

View File

@ -46,6 +46,7 @@ _Past.prototype.onMessage = function(controller, msg_type, message) {
'DeviceMove',
'DeviceLabelEdit',
'GroupLabelEdit',
'GroupCreate',
'LinkLabelEdit',
'InterfaceLabelEdit',
'InterfaceCreate',
@ -274,6 +275,7 @@ _Present.prototype.onMessage = function(controller, msg_type, message) {
'DeviceMove',
'DeviceLabelEdit',
'GroupLabelEdit',
'GroupCreate',
'InterfaceCreate',
'InterfaceLabelEdit',
'LinkCreate',
@ -314,6 +316,11 @@ _Present.prototype.onDeviceCreate = function(controller, msg_type, message) {
controller.scope.onDeviceCreate(message);
}
};
_Present.prototype.onGroupCreate = function(controller, msg_type, message) {
if (message.sender !== controller.scope.client_id) {
controller.scope.onGroupCreate(message);
}
};
_Present.prototype.onInterfaceCreate = function(controller, msg_type, message) {
if (message.sender !== controller.scope.client_id) {
controller.scope.onInterfaceCreate(message);

View File

@ -0,0 +1,216 @@
var inherits = require('inherits');
var fsm = require('./fsm.js');
function _State () {
}
inherits(_State, fsm._State);
function _Dropping () {
this.name = 'Dropping';
}
inherits(_Dropping, _State);
var Dropping = new _Dropping();
exports.Dropping = Dropping;
function _Selecting () {
this.name = 'Selecting';
}
inherits(_Selecting, _State);
var Selecting = new _Selecting();
exports.Selecting = Selecting;
function _Selected () {
this.name = 'Selected';
}
inherits(_Selected, _State);
var Selected = new _Selected();
exports.Selected = Selected;
function _Ready () {
this.name = 'Ready';
}
inherits(_Ready, _State);
var Ready = new _Ready();
exports.Ready = Ready;
function _Scrolling () {
this.name = 'Scrolling';
}
inherits(_Scrolling, _State);
var Scrolling = new _Scrolling();
exports.Scrolling = Scrolling;
function _Start () {
this.name = 'Start';
}
inherits(_Start, _State);
var Start = new _Start();
exports.Start = Start;
function _Move () {
this.name = 'Move';
}
inherits(_Move, _State);
var Move = new _Move();
exports.Move = Move;
_Dropping.prototype.start = function (controller) {
var i = 0;
var toolbox = controller.toolbox;
console.log(["Dropping", toolbox.selected_item]);
for(i = 0; i < toolbox.items.length; i++) {
toolbox.items[i].selected = false;
}
controller.dropped_action(toolbox.selected_item);
if (controller.remove_on_drop) {
var dindex = toolbox.items.indexOf(toolbox.selected_item);
if (dindex !== -1) {
toolbox.items.splice(dindex, 1);
}
}
toolbox.selected_item = null;
controller.changeState(Ready);
};
_Dropping.prototype.start.transitions = ['Ready'];
_Selected.prototype.onMouseMove = function (controller) {
controller.changeState(Move);
};
_Selected.prototype.onMouseMove.transitions = ['Move'];
_Selected.prototype.onMouseUp = function (controller) {
var i = 0;
var toolbox = controller.toolbox;
for(i = 0; i < toolbox.items.length; i++) {
toolbox.items[i].selected = false;
}
toolbox.selected_item = null;
controller.changeState(Ready);
};
_Selected.prototype.onMouseUp.transitions = ['Move'];
_Selecting.prototype.onMouseDown = function (controller) {
var i = 0;
var toolbox = controller.toolbox;
var scope = controller.scope;
var selected_item = Math.floor((controller.scope.mouseY - toolbox.y - toolbox.scroll_offset) / toolbox.spacing);
for(i = 0; i < toolbox.items.length; i++) {
toolbox.items[i].selected = false;
}
if (selected_item >= 0 && selected_item < toolbox.items.length) {
toolbox.items[selected_item].selected = true;
toolbox.selected_item = toolbox.items[selected_item];
scope.pressedX = scope.mouseX;
scope.pressedY = scope.mouseY;
scope.pressedScaledX = scope.scaledX;
scope.pressedScaledY = scope.scaledY;
toolbox.selected_item.x = toolbox.x + toolbox.width/2;
toolbox.selected_item.y = selected_item * toolbox.spacing + toolbox.y + toolbox.scroll_offset + toolbox.spacing/2;
controller.scope.clear_selections();
controller.scope.first_controller.handle_message("UnselectAll", {});
controller.changeState(Selected);
} else {
toolbox.selected_item = null;
controller.changeState(Ready);
}
};
_Selecting.prototype.onMouseDown.transitions = ['Selected'];
_Ready.prototype.onMouseDown = function (controller, msg_type, $event) {
if(controller.toolbox.enabled &&
controller.scope.mouseX > controller.toolbox.x &&
controller.scope.mouseY > controller.toolbox.y &&
controller.scope.mouseX < controller.toolbox.x + controller.toolbox.width &&
controller.scope.mouseY < controller.toolbox.y + controller.toolbox.height) {
controller.changeState(Selecting);
controller.handle_message(msg_type, $event);
} else {
controller.next_controller.handle_message(msg_type, $event);
}
};
_Ready.prototype.onMouseDown.transitions = ['Selecting'];
_Ready.prototype.onMouseWheel = function (controller, msg_type, $event) {
if(controller.toolbox.enabled &&
controller.scope.mouseX > controller.toolbox.x &&
controller.scope.mouseY > controller.toolbox.y &&
controller.scope.mouseX < controller.toolbox.x + controller.toolbox.width &&
controller.scope.mouseY < controller.toolbox.y + controller.toolbox.height) {
controller.changeState(Scrolling);
controller.handle_message(msg_type, $event);
} else {
controller.next_controller.handle_message(msg_type, $event);
}
};
_Ready.prototype.onMouseWheel.transitions = ['Scrolling'];
_Scrolling.prototype.onMouseWheel = function (controller, msg_type, $event) {
var delta = $event[1];
controller.toolbox.scroll_offset += -1 * delta;
controller.toolbox.scroll_offset = Math.min(controller.toolbox.scroll_offset, 0);
controller.toolbox.scroll_offset = Math.max(controller.toolbox.scroll_offset, -1 * controller.toolbox.spacing * controller.toolbox.items.length + controller.toolbox.height);
controller.changeState(Ready);
};
_Scrolling.prototype.start.transitions = ['Ready'];
_Start.prototype.start = function (controller) {
controller.changeState(Ready);
};
_Start.prototype.start.transitions = ['Ready'];
_Move.prototype.onMouseUp = function (controller) {
controller.changeState(Dropping);
};
_Move.prototype.onMouseUp.transitions = ['Dropping'];
_Move.prototype.onMouseMove = function (controller) {
var diffX = controller.scope.mouseX - controller.scope.pressedX;
var diffY = controller.scope.mouseY - controller.scope.pressedY;
controller.toolbox.selected_item.x += diffX;
controller.toolbox.selected_item.y += diffY;
controller.scope.pressedX = controller.scope.mouseX;
controller.scope.pressedY = controller.scope.mouseY;
};

View File

@ -95,7 +95,7 @@ _Start.prototype.start = function (controller) {
_Scale.prototype.onMouseWheel = function (controller, msg_type, message) {
var delta = message[1];
var new_scale = Math.max(0.1, Math.min(10, (controller.scope.current_scale + delta / 100)));
var new_scale = Math.max(0.001, Math.min(100, (controller.scope.current_scale + delta / (100 / controller.scope.current_scale))));
var new_panX = controller.scope.mouseX - new_scale * ((controller.scope.mouseX - controller.scope.panX) / controller.scope.current_scale);
var new_panY = controller.scope.mouseY - new_scale * ((controller.scope.mouseY - controller.scope.panY) / controller.scope.current_scale);
controller.scope.updateScaledXY();

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html ng-app="networkWidgets">
<head>
<link rel="stylesheet" href="css/style.css" />
<script src="js/vendor.bundle.js"></script>
<script src="js/bundle.js"></script>
</head>
<body style="margin: 0px">
<awx-network-widgets></awx-network-widgets>
</body>
</html>

View File

@ -0,0 +1,3 @@
<g ng-attr-transform="translate({{item.x}}, {{item.y}}">
<path d="M100,100 h200 a20,20 0 0 1 20,20 v200 a20,20 0 0 1 -20,20 h-200 a20,20 0 0 1 -20,-20 v-200 a20,20 0 0 1 20,-20 z" fill="none" stroke="black" stroke-width="3" />
</g>

View File

@ -1,6 +1,10 @@
<g ng-attr-class="{{debug.hidden && 'NetworkUI--hidden' || ''}}">
<text ng-attr-x="{{graph.right_column}}" y="35" class="NetworkUI__debug-text">view_port.x: {{view_port.x}}</text>
<text ng-attr-x="{{graph.right_column}}" y="55" class="NetworkUI__debug-text">view_port.y: {{view_port.y}}</text>
<text ng-attr-x="{{graph.right_column}}" y="75" class="NetworkUI__debug-text">view_port.width: {{view_port.width}}</text>
<text ng-attr-x="{{graph.right_column}}" y="95" class="NetworkUI__debug-text">view_port.height: {{view_port.height}}</text>
<text ng-attr-x="{{graph.right_column}}" y="115" class="NetworkUI__debug-text">width: {{graph.width}}</text>
<text ng-attr-x="{{graph.right_column}}" y="135" class="NetworkUI__debug-text">height: {{graph.height}}</text>
<text ng-attr-x="{{graph.right_column}}" y="155" class="NetworkUI__debug-text">rc: {{graph.right_column}}</text>
@ -10,7 +14,7 @@
<text ng-attr-x="{{graph.right_column}}" y="235" class="NetworkUI__debug-text">Mouse over: {{onMouseOverResult}}</text>
<text ng-attr-x="{{graph.right_column}}" y="255" class="NetworkUI__debug-text">Mouse enter: {{onMouseEnterResult}}</text>
<text ng-attr-x="{{graph.right_column}}" y="275" class="NetworkUI__debug-text">Mouse leave: {{onMouseLeaveResult}}</text>
<text ng-attr-x="{{graph.right_column}}" y="295" class="NetworkUI__debug-text">Current scale: {{current_scale.toFixed(2)}}</text>
<text ng-attr-x="{{graph.right_column}}" y="295" class="NetworkUI__debug-text">Current scale: {{current_scale.toFixed(4)}}</text>
<text ng-attr-x="{{graph.right_column}}" y="315" class="NetworkUI__debug-text">Pan X: {{panX.toFixed(2)}}</text>
<text ng-attr-x="{{graph.right_column}}" y="335" class="NetworkUI__debug-text">Pan Y: {{panY.toFixed(2)}}</text>
<text ng-attr-x="{{graph.right_column}}" y="355" class="NetworkUI__debug-text">View State: {{view_controller.state.name}}</text>
@ -32,4 +36,10 @@
<text ng-attr-x="{{graph.right_column}}" y="675" class="NetworkUI__debug-text">Group State: {{group_controller.state.name}}</text>
<text ng-attr-x="{{graph.right_column}}" y="695" class="NetworkUI__debug-text">Selected groups: {{selected_groups.length}}</text>
<text ng-attr-x="{{graph.right_column}}" y="715" class="NetworkUI__debug-text">Hotkeys State: {{hotkeys_controller.state.name}}</text>
<text ng-attr-x="{{graph.right_column}}" y="735" class="NetworkUI__debug-text">Mode State: {{mode_controller.state.name}}</text>
<text ng-attr-x="{{graph.right_column}}" y="755" class="NetworkUI__debug-text">Device Detail State: {{device_detail_controller.state.name}}</text>
<text ng-attr-x="{{graph.right_column}}" y="775" class="NetworkUI__debug-text">Site State: {{site_controller.state.name}}</text>
<text ng-attr-x="{{graph.right_column}}" y="795" class="NetworkUI__debug-text">Rack State: {{rack_controller.state.name}}</text>
<text ng-attr-x="{{graph.right_column}}" y="815" class="NetworkUI__debug-text">Stream State: {{stream_controller.state.name}}</text>
<rect x=10 y=10 ng-attr-width="{{graph.width - 20}}" ng-attr-height="{{graph.height - 20}}" class="NetworkUI--debug"></rect>
</g>

View File

@ -1,36 +1,53 @@
<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">
<line ng-attr-x1="{{-50 - 10}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 10}}"
ng-attr-y2="0"
ng-attr-class="{{debug.hidden && 'hidden' || ''}} debug" />
class="NetworkUI--debug"></rect>
<line ng-attr-x1="0"
ng-attr-y1="{{-50 - 10}}"
ng-attr-x2="0"
ng-attr-y2="{{50 + 10}}"
ng-attr-class="{{debug.hidden && 'hidden' || ''}} debug" />
class="NetworkUI--debug"></rect>
<rect ng-attr-x="{{-50}}"
ng-attr-y="{{-50}}"
ng-attr-width="{{50 * 2}}"
ng-attr-height="{{50 * 2}}"
ng-attr-class="{{debug.hidden && 'hidden' || ''}} debug" />
class="NetworkUI--debug"></rect>
</g>
<g class="NetworkUI__device">
<circle
cx="0"
cy="0"
ng-attr-r="{{50 + 2}}"
ng-attr-class="{{device.selected || device.remote_selected ? device.selected && device.remote_selected ? 'selected-conflict' : device.selected ? 'selected' : 'remote-selected' : 'hidden'}}">
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__device--selected-conflict' : item.selected ? 'NetworkUI__device--selected' : 'NetworkUI__device--remote-selected' : 'NetworkUI--hidden'}}">
</circle>
<circle
cx="0"
cy="0"
ng-attr-r="{{50}}">
</circle>
<g ng-show="current_scale > 0.5">
<text ng-attr-class="{{device.selected && ! device.edit_label ? 'selected' : 'hidden'}}"
</g>
<g ng-show="item.icon || current_scale > 0.5">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__device-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
text-anchor="middle"
x="0"
y="75"> {{device.name}} </text>
<text text-anchor="middle" x="0" y="75">{{device.name}}{{device.edit_label?'_':''}}</text>
y="0"> {{item.name}} </text>
<text class="NetworkUI__device-text" text-anchor="middle" x="0" y="0">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>

View File

@ -0,0 +1,109 @@
<g ng-attr-transform="scale({{1/5}}) translate(-250,-250)">
<rect width=500
height=500
x=0
y=0
class="NetworkUI__group"/>
<g ng-attr-transform="translate(0,0)"
ng-attr-class="{{item.type}}"
ng-switch on="item.type">
<g ng-switch-when="router"><!-- begin router -->
<g awx-net-router></g>
</g> <!-- end router -->
<g ng-switch-when="switch"> <!-- begin switch -->
<g awx-net-switch> </g>
</g> <!-- end switch -->
<g ng-switch-when="host"> <!-- begin host -->
<g awx-net-host> </g>
</g> <!-- end host -->
<g ng-switch-default> <!-- begin default -->
<g awx-net-default></g>
</g> <!-- end default -->
<g awx-net-status-light></g>
<g awx-net-task-status></g>
</g> <!-- end transform class switch -->
<g transform="translate(0, 500)">
<g ng-repeat="interface in item.interfaces track by $index">
<g ng-attr-transform="translate({{$index * 60 + 30}}, -40)">
<g ng-if="interface.link !== null">
<line x1="0"
y1="0"
x2="0"
y2="100"
class="{{interface.link.status === null ? 'NetworkUI__link' : interface.link.status ? 'NetworkUI__link--link-pass' : 'NetworkUI__link--link-fail'}}"/>
</g>
<circle cx="0"
cy="0"
r=14
ng-attr-class="{{interface.selected ? 'NetworkUI__interface--selected' : 'NetworkUI--hidden'}}" ></circle>
<circle cx="0"
cy="0"
r=10
class="NetworkUI__interface" ></circle>
<text ng-attr-class="{{interface.selected && ! interface.edit_label ? 'NetworkUI__interface-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
text-anchor="middle"
x="0"
y="-15"> {{interface.name}}</text>
<text class="NetworkUI__interface-text" text-anchor="middle" x="0" y="-15">{{interface.name}}{{interface.edit_label?'_':''}}</text>
<g ng-if="interface.remote_interface() !== null">
<circle cx="0"
cy="100"
r=14
ng-attr-class="{{interface.remote_interface().selected ? 'NetworkUI__interface--selected' : 'NetworkUI--hidden'}}" ></circle>
<circle cx="0"
cy="100"
r=10
class="NetworkUI__interface" ></circle>
</g>
<text class="NetworkUI__interface-text" text-anchor="middle" x="0" y="85">{{interface.remote_interface().name}}</text>
<g ng-repeat="item in [interface.remote_interface().device]">
<g ng-attr-transform="translate(0,100) scale(0.5) translate(0, {{item.height}})"
ng-attr-class="{{item.type}}"
ng-switch on="item.type">
<g ng-switch-when="router"><!-- begin router -->
<g awx-net-router></g>
</g> <!-- end router -->
<g ng-switch-when="switch"> <!-- begin switch -->
<g awx-net-switch> </g>
</g> <!-- end switch -->
<g ng-switch-when="host"> <!-- begin host -->
<g awx-net-host> </g>
</g> <!-- end host -->
<g ng-switch-default> <!-- begin default -->
</g> <!-- end default -->
</g> <!-- end transform class switch -->
</g> <!-- end repeat -->
</g> <!-- end transform -->
</g> <!-- end ng-repeat interface -->
</g> <!-- end transform translate -->
<g transform="translate(0, 100)">
<g ng-repeat="item in item.processes track by $index">
<g ng-attr-transform="translate({{$index * 75 + 50}}, 0) scale(0.5)">
<g awx-net-process></g>
</g> <!-- end translate -->
</g> <!-- end ng-repeat process -->
</g> <!-- end translate -->
</g> <!-- end transform scale translate -->

View File

@ -1,70 +1,131 @@
<g ng-if="!hide_groups">
<rect ng-attr-width="{{group.width(scaledX)}}"
ng-attr-height="{{group.height(scaledY)}}"
ng-attr-x="{{group.left_extent(scaledX)}}"
ng-attr-y="{{group.top_extent(scaledY)}}"
ng-attr-class="{{group.selected && 'NetworkUI__group--selected' || 'NetworkUI--hidden'}}"/>
<g ng-if="!hide_groups || item.type == 'site'">
<g ng-if="current_scale > 0.5 || item.type == 'site' || (item.type == 'rack' && current_scale > 0.1)" >
<g ng-if="item.moving">
<g ng-attr-transform="translate({{item.left_extent(scaledX)}}, {{item.top_extent(scaledY)}})">
<line x1="-100"
y1="0"
x2="+100"
y2="0"
class="NetworkUI--construction"></line>
<line x1="0"
y1="-100"
x2="0"
y2="+100"
class="NetworkUI--construction"></line>
</g>
<g ng-attr-transform="translate({{item.right_extent(scaledX)}}, {{item.top_extent(scaledY)}})">
<line x1="-100"
y1="0"
x2="+100"
y2="0"
class="NetworkUI--construction"></line>
<line x1="0"
y1="-100"
x2="0"
y2="+100"
class="NetworkUI--construction"></line>
</g>
<g ng-attr-transform="translate({{item.left_extent(scaledX)}}, {{item.bottom_extent(scaledY)}})">
<line x1="-100"
y1="0"
x2="+100"
y2="0"
class="NetworkUI--construction"></line>
<line x1="0"
y1="-100"
x2="0"
y2="+100"
class="NetworkUI--construction"></line>
</g>
<g ng-attr-transform="translate({{item.right_extent(scaledX)}}, {{item.bottom_extent(scaledY)}})">
<line x1="-100"
y1="0"
x2="+100"
y2="0"
class="NetworkUI--construction"></line>
<line x1="0"
y1="-100"
x2="0"
y2="+100"
class="NetworkUI--construction"></line>
</g>
</g>
<rect ng-attr-width="{{item.width(scaledX)}}"
ng-attr-height="{{item.height(scaledY)}}"
ng-attr-x="{{item.left_extent(scaledX)}}"
ng-attr-y="{{item.top_extent(scaledY)}}"
ng-attr-class="{{item.selected && 'NetworkUI__group--selected' || 'NetworkUI--hidden'}}"/>
<rect ng-attr-width="10"
ng-attr-height="10"
ng-attr-x="{{group.left_extent(scaledX)}}"
ng-attr-y="{{group.top_extent(scaledY)}}"
ng-attr-class="{{group.selected && 'NetworkUI__group--selected' || 'NetworkUI--hidden'}}"/>
ng-attr-x="{{item.left_extent(scaledX)}}"
ng-attr-y="{{item.top_extent(scaledY)}}"
ng-attr-class="{{item.selected && 'NetworkUI__group--selected' || 'NetworkUI--hidden'}}"/>
<rect ng-attr-width="10"
ng-attr-height="10"
ng-attr-x="{{group.right_extent(scaledX) - 10}}"
ng-attr-y="{{group.top_extent(scaledY)}}"
ng-attr-class="{{group.selected && 'NetworkUI__group--selected' || 'NetworkUI--hidden'}}"/>
ng-attr-x="{{item.right_extent(scaledX) - 10}}"
ng-attr-y="{{item.top_extent(scaledY)}}"
ng-attr-class="{{item.selected && 'NetworkUI__group--selected' || 'NetworkUI--hidden'}}"/>
<rect ng-attr-width="10"
ng-attr-height="10"
ng-attr-x="{{group.right_extent(scaledX) - 10}}"
ng-attr-y="{{group.bottom_extent(scaledY) - 10}}"
ng-attr-class="{{group.selected && 'NetworkUI__group--selected' || 'NetworkUI--hidden'}}"/>
ng-attr-x="{{item.right_extent(scaledX) - 10}}"
ng-attr-y="{{item.bottom_extent(scaledY) - 10}}"
ng-attr-class="{{item.selected && 'NetworkUI__group--selected' || 'NetworkUI--hidden'}}"/>
<rect ng-attr-width="10"
ng-attr-height="10"
ng-attr-x="{{group.left_extent(scaledX)}}"
ng-attr-y="{{group.bottom_extent(scaledY) - 10}}"
ng-attr-class="{{group.selected && 'NetworkUI__group--selected' || 'NetworkUI--hidden'}}"/>
ng-attr-x="{{item.left_extent(scaledX)}}"
ng-attr-y="{{item.bottom_extent(scaledY) - 10}}"
ng-attr-class="{{item.selected && 'NetworkUI__group--selected' || 'NetworkUI--hidden'}}"/>
<g ng-if="group.highlighted || group.selected">
<g ng-if="item.highlighted || item.selected">
<rect ng-attr-width="10"
ng-attr-height="10"
ng-attr-x="{{group.left_extent(scaledX)}}"
ng-attr-y="{{group.top_extent(scaledY)}}"
ng-attr-x="{{item.left_extent(scaledX)}}"
ng-attr-y="{{item.top_extent(scaledY)}}"
class="NetworkUI__group"/>
<rect ng-attr-width="10"
ng-attr-height="10"
ng-attr-x="{{group.right_extent(scaledX) - 10}}"
ng-attr-y="{{group.top_extent(scaledY)}}"
ng-attr-x="{{item.right_extent(scaledX) - 10}}"
ng-attr-y="{{item.top_extent(scaledY)}}"
class="NetworkUI__group"/>
<rect ng-attr-width="10"
ng-attr-height="10"
ng-attr-x="{{group.right_extent(scaledX) - 10}}"
ng-attr-y="{{group.bottom_extent(scaledY) - 10}}"
ng-attr-x="{{item.right_extent(scaledX) - 10}}"
ng-attr-y="{{item.bottom_extent(scaledY) - 10}}"
class="NetworkUI__group"/>
<rect ng-attr-width="10"
ng-attr-height="10"
ng-attr-x="{{group.left_extent(scaledX)}}"
ng-attr-y="{{group.bottom_extent(scaledY) - 10}}"
ng-attr-x="{{item.left_extent(scaledX)}}"
ng-attr-y="{{item.bottom_extent(scaledY) - 10}}"
class="NetworkUI__group"/>
</g>
<rect ng-attr-width="{{group.width(scaledX)}}"
ng-attr-height="{{group.height(scaledY)}}"
ng-attr-x="{{group.left_extent(scaledX)}}"
ng-attr-y="{{group.top_extent(scaledY)}}"
<rect ng-attr-width="{{item.width(scaledX)}}"
ng-attr-height="{{item.height(scaledY)}}"
ng-attr-x="{{item.left_extent(scaledX)}}"
ng-attr-y="{{item.top_extent(scaledY)}}"
class="NetworkUI__group"/>
<text ng-attr-class="{{group.selected && ! group.edit_label ? 'NetworkUI__group-text--selected' : 'NetworkUI--hidden'}}"
<g ng-attr-transform="translate({{item.left_extent(scaledX)}},{{item.top_extent(scaledY)}})">
<g ng-if="current_scale > 0.5 || item.type == 'site' || item.type == 'rack'">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__group-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
text-anchor="left"
ng-attr-x="{{group.left_extent(scaledX) + 20}}"
ng-attr-y="{{group.top_extent(scaledY) + 32}}"> {{group.name}} </text>
<text class="NetworkUI__group-text" text-anchor="left" ng-attr-x="{{group.left_extent(scaledX) + 20}}" ng-attr-y="{{group.top_extent(scaledY) + 32}}">{{group.name}}{{group.edit_label?'_':''}}</text>
x="20"
y="32"> {{item.name}} </text>
<text class="NetworkUI__group-text" text-anchor="left" x="20" y="32">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
<g awx-net-rack></g>
<g awx-net-site></g>
</g>
</g>
</g>

View File

@ -1,5 +1,18 @@
<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>
<g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}"
ng-attr-y1="0"
@ -23,7 +36,7 @@
y="-17"
ng-attr-width="{{100 + 4}}"
ng-attr-height="{{30 + 4}}"
ng-attr-class="{{device.selected || device.remote_selected ? device.selected && device.remote_selected ? 'NetworkUI__host--selected-conflict' : device.selected ? 'NetworkUI__host--selected' : 'NetworkUI__host--remote-selected' : 'NetworkUI--hidden'}}"
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
@ -36,11 +49,11 @@
<circle cx="30" cy="0" r=7 />
</circle>
</g>
<g ng-show="current_scale > 0.5">
<text ng-attr-class="{{device.selected && ! device.edit_label ? 'NetworkUI__host-text--selected' : 'NetworkUI--hidden'}}"
<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"> {{device.name}} </text>
<text class="NetworkUI__host-text" text-anchor="middle" x="0" y="5">{{device.name}}{{device.edit_label?'_':''}}</text>
y="5"> {{item.name}} </text>
<text class="NetworkUI__host-text" text-anchor="middle" x="0" y="5">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>

View File

@ -0,0 +1,96 @@
<g ng-if="toolbox.enabled">
<rect class="NetworkUI__toolbox"
ng-attr-x="{{toolbox.x}}"
ng-attr-y="{{toolbox.y}}"
ng-attr-width="{{toolbox.width}}"
ng-attr-height="{{toolbox.height}}"
rx=5></rect>
<g clip-path="url(#inventory-toolbox-clip-path)">
<g ng-attr-transform="translate({{toolbox.x}}, {{toolbox.y}})">
<g ng-repeat="item in toolbox.items track by $index"
ng-attr-transform="translate({{toolbox.width/2}},{{$index * toolbox.spacing + toolbox.spacing/2 + toolbox.scroll_offset}})"
ng-attr-class="{{item.type}}"
ng-switch on="item.type">
<g ng-switch-when="router"><!-- begin router -->
<g awx-net-router></g>
</g> <!-- end router -->
<g ng-switch-when="switch"> <!-- begin switch -->
<g awx-net-switch> </g>
</g> <!-- end switch -->
<g ng-switch-when="host"> <!-- begin host -->
<g awx-net-host> </g>
</g> <!-- end host -->
<g ng-switch-when="site"> <!-- begin site -->
<g awx-net-site-icon> </g>
</g> <!-- end site -->
<g ng-switch-when="rack"> <!-- begin rack -->
<g awx-net-rack-icon> </g>
</g> <!-- end rack -->
<g ng-switch-when="process"> <!-- begin site -->
<g awx-net-process> </g>
</g> <!-- end site -->
<g ng-switch-when="configuration"> <!-- begin site -->
<g awx-net-configuration> </g>
</g> <!-- end site -->
<g ng-switch-default> <!-- begin default -->
<g awx-net-default></g>
</g> <!-- end default -->
</g> <!-- end devices -->
</g> <!-- end transform -->
</g> <!-- end clip path -->
<rect class="NetworkUI__toolbox-bezel"
ng-attr-x="{{toolbox.x}}"
ng-attr-y="{{toolbox.y}}"
ng-attr-width="{{toolbox.width}}"
ng-attr-height="{{toolbox.height}}"
rx=5></rect>
<!-- selected item-->
<g ng-if="toolbox.selected_item != null">
<g ng-repeat="item in [toolbox.selected_item]"
ng-attr-transform="translate({{item.x}}, {{item.y}})"
ng-attr-class="{{item.type}}"
ng-switch on="item.type">
<g ng-switch-when="router"><!-- begin router -->
<g awx-net-router></g>
</g> <!-- end router -->
<g ng-switch-when="switch"> <!-- begin switch -->
<g awx-net-switch> </g>
</g> <!-- end switch -->
<g ng-switch-when="host"> <!-- begin host -->
<g awx-net-host> </g>
</g> <!-- end host -->
<g ng-switch-when="site"> <!-- begin site -->
<g awx-net-site-icon> </g>
</g> <!-- end site -->
<g ng-switch-when="rack"> <!-- begin rack -->
<g awx-net-rack-icon> </g>
</g> <!-- end rack -->
<g ng-switch-when="process"> <!-- begin site -->
<g awx-net-process> </g>
</g> <!-- end site -->
<g ng-switch-when="configuration"> <!-- begin site -->
<g awx-net-configuration> </g>
</g> <!-- end site -->
<g ng-switch-default> <!-- begin default -->
<g awx-net-default></g>
</g> <!-- end default -->
</g> <!-- end selected item -->
</g> <!-- ng-if -->
</g> <!-- ng-if toolbox.enabled -->

View File

@ -0,0 +1,6 @@
<rect ng-attr-x="{{toolbox.x}}"
ng-attr-y="{{toolbox.y}}"
ng-attr-width="{{toolbox.width}}"
ng-attr-height="{{toolbox.height}}"
rx=5></rect>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 966 KiB

View File

@ -22,21 +22,38 @@
<feFlood flood-color="#ffffff"/>
<feComposite in="SourceGraphic" operator="xor"/>
</filter>
<clipPath id="inventory-toolbox-clip-path">
<rect ng-attr-x="{{inventory_toolbox.x}}"
ng-attr-y="{{inventory_toolbox.y}}"
ng-attr-width="{{inventory_toolbox.width}}"
ng-attr-height="{{inventory_toolbox.height}}"
rx=5></rect>
</clipPath>
</defs>
<g transform="scale(1.0)" id="frame_g">
<g ng-if="current_mode == 'MultiSite'" transform="translate(-300000, -200000) scale(1000)" awx-net-map></g>
<g ng-if="!hide_links">
<g ng-if="current_scale > 0.5 && current_scale < 5">
<g ng-repeat="link in links">
<g awx-net-link></g>
</g>
</g>
</g> <!-- end ng-repeat link in links-->
</g> <!-- end ng-if current_scale -->
</g> <!-- end hide_links -->
<g ng-repeat="link in links">
<g ng-if="link.selected || link.to_interface.selected || link.from_interface.selected" link></g>
</g>
<g ng-repeat="device in devices"
ng-attr-transform="translate({{device.x}},{{device.y}})"
ng-attr-class="{{device.type}}"
ng-switch on="device.type">
<g ng-switch-when="router"><!-- begin router -->
<g ng-if="current_scale > 0.5 && current_scale < 5">
<g ng-repeat="stream in streams">
<g awx-net-stream></g>
</g> <!-- end ng-repeat stream in streams-->
</g> <!-- end ng-if current_scale -->
<g ng-if="current_scale > 0.5 && current_scale < 5">
<g ng-repeat="item in devices"
ng-attr-transform="translate({{item.x}},{{item.y}})"
ng-attr-class="{{item.type}}"
ng-switch on="item.type">
<g ng-switch-when="router"><!-- begin router -->
<g awx-net-router></g>
</g> <!-- end router -->
@ -49,17 +66,21 @@
</g> <!-- end host -->
<g ng-switch-when="rack"> <!-- begin rack -->
<g awx-net-rack> </g>
</g> <!-- end rack -->
<g ng-switch-default> <!-- begin default -->
<g awx-net-default></g>
</g> <!-- end default -->
<g awx-net-status-light></g>
<g awx-net-task-status></g>
</g> <!-- end devices -->
<g ng-repeat="group in groups">
</g>
<g ng-if="current_scale >= 5">
<g ng-repeat="item in devices"
ng-attr-transform="translate({{item.x}},{{item.y}})">
<g awx-net-device-detail> </g>
</g>
</g>
<g ng-repeat="item in groups">
<g awx-net-group></g>
</g>
<g ng-attr-transform="translate({{scaledX}},{{scaledY}})" ng-attr-class="{{debug.hidden && 'hidden' || ''}} debug-cursor" >
@ -69,6 +90,9 @@
<g awx-net-quadrants>
</g>
</g>
<g ng-repeat="toolbox in [site_toolbox, rack_toolbox, inventory_toolbox, app_toolbox]">
<g awx-net-inventory-toolbox></g>
</g>
<g ng-if="!hide_buttons">
<g> <!-- buttons -->
<g ng-repeat="button in buttons"
@ -98,5 +122,8 @@
<g ng-repeat="touch in touches">
<g awx-net-touch></g>
</g>
<g ng-repeat="l in current_location track by $index">
<text x="10" ng-attr-y="{{20 * (1 + $index)}}" text-anchor="left" class="NetworkUI__location-text">{{l}}</text>
</g>
</svg>
</div>

View File

@ -0,0 +1,126 @@
<div ng-controller="NetworkWidgetsController">
<svg id="frame" class="NetworkUI"
ng-attr-height="{{graph.height}}"
ng-attr-width="{{graph.width}}"
ng-mousedown="onMouseDown($event)"
ng-mouseup="onMouseUp($event)"
ng-mouseenter="onMouseEnter($event)"
ng-mouseleave="onMouseLeave($event)"
ng-mousemove="onMouseMove($event)"
ng-mouseover="onMouseOver($event)"
ng-touchstart="onTouchStart($event)"
ng-touchmove="onTouchMove($event)"
ng-touchend="onTouchEnd($event)"
ng-tap="onTap($event)"
msd-wheel="onMouseWheel($event, $delta, $deltaX, $deltaY)">
<defs>
<filter x="0" y="0" width="1" height="1" id="selected">
<feFlood flood-color="#b3d8fd"/>
<feComposite in="SourceGraphic" operator="xor"/>
</filter>
<filter x="0" y="0" width="1" height="1" id="background">
<feFlood flood-color="#ffffff"/>
<feComposite in="SourceGraphic" operator="xor"/>
</filter>
<clipPath id="inventory-toolbox-clip-path">
<rect ng-attr-x="{{inventory_toolbox.x}}"
ng-attr-y="{{inventory_toolbox.y}}"
ng-attr-width="{{inventory_toolbox.width}}"
ng-attr-height="{{inventory_toolbox.height}}"
rx=5></rect>
</clipPath>
</defs>
<g transform="scale(1.0)" id="frame_g">
<g ng-if="current_mode == 'MultiSite'" transform="translate(-300000, -200000) scale(1000)" awx-net-map></g>
<g ng-if="!hide_links">
<g ng-if="current_scale > 0.5 && current_scale < 5">
<g ng-repeat="link in links">
<g awx-net-link></g>
</g> <!-- end ng-repeat link in links-->
</g> <!-- end ng-if current_scale -->
</g> <!-- end hide_links -->
<g ng-repeat="link in links">
<g ng-if="link.selected || link.to_interface.selected || link.from_interface.selected" link></g>
</g>
<g ng-if="current_scale > 0.5 && current_scale < 5">
<g ng-repeat="stream in streams">
<g awx-net-stream></g>
</g> <!-- end ng-repeat stream in streams-->
</g> <!-- end ng-if current_scale -->
<g ng-if="current_scale > 0.5 && current_scale < 5">
<g ng-repeat="item in devices"
ng-attr-transform="translate({{item.x}},{{item.y}})"
ng-attr-class="{{item.type}}"
ng-switch on="item.type">
<g ng-switch-when="router"><!-- begin router -->
<g awx-net-router></g>
</g> <!-- end router -->
<g ng-switch-when="switch"> <!-- begin switch -->
<g awx-net-switch> </g>
</g> <!-- end switch -->
<g ng-switch-when="host"> <!-- begin host -->
<g awx-net-host> </g>
</g> <!-- end host -->
<g ng-switch-default> <!-- begin default -->
<g awx-net-default></g>
</g> <!-- end default -->
<g awx-net-status-light></g>
<g awx-net-task-status></g>
</g> <!-- end devices -->
</g>
<g ng-if="current_scale >= 5">
<g ng-repeat="item in devices"
ng-attr-transform="translate({{item.x}},{{item.y}})">
<g awx-net-device-detail> </g>
</g>
</g>
<g ng-repeat="item in groups">
<g awx-net-group></g>
</g>
<g ng-attr-transform="translate({{scaledX}},{{scaledY}})" ng-attr-class="{{debug.hidden && 'hidden' || ''}} debug-cursor" >
<line x1="-5" y1="0" x2="5" y2="0"/>
<line x1="0" y1="-5" x2="0" y2="5"/>
</g>
<g awx-net-quadrants>
</g>
</g>
<g ng-repeat="toolbox in [site_toolbox, rack_toolbox, inventory_toolbox, app_toolbox]">
<g awx-net-inventory-toolbox></g>
</g>
<g ng-if="!hide_buttons">
<g> <!-- buttons -->
<g ng-repeat="button in buttons"
ng-attr-transform="translate({{button.x}},{{button.y}})">
<g awx-net-button></g>
</g>
</g> <!-- end buttons -->
<g> <!-- stencils -->
<g ng-repeat="stencil in stencils"
ng-attr-transform="translate({{stencil.x}},{{stencil.y}})"
class="button">
<g awx-net-stencil></g>
</g>
</g> <!-- end stencils -->
<g> <!-- layers -->
<g ng-repeat="layer in layers"
ng-attr-transform="translate({{layer.x}},{{layer.y}})"
class="button">
<g awx-net-layer> </g>
</g>
</g> <!-- end layers -->
</g>
<g awx-net-debug></g>
<g awx-net-cursor></g>
<g ng-repeat="touch in touches">
<g awx-net-touch></g>
</g>
</svg>
</div>

View File

@ -0,0 +1,11 @@
<g class="NetworkUI__process" ng-attr-transform="translate(-50, -50)">
<path 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'}}"
d="M0,0 h100 a10,10 0 0 1 10,10 v100 a10,10 0 0 1 -10,10 h-100 a10,10 0 0 1 -10,-10 v-100 a10,10 0 0 1 10,-10 z" />
<path d="M0,0 h100 a10,10 0 0 1 10,10 v100 a10,10 0 0 1 -10,10 h-100 a10,10 0 0 1 -10,-10 v-100 a10,10 0 0 1 10,-10 z" />
</g>
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__process-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
text-anchor="middle"
x="0"
y="12"> {{item.name}} </text>
<text class="NetworkUI__process-text" text-anchor="middle" x="0" y="12">{{item.name}}{{item.edit_label?'_':''}}</text>

View File

@ -1,10 +1,16 @@
<line ng-attr-x1="-100000"
ng-attr-y1="0"
ng-attr-x2="100000"
ng-attr-y2="0"
<line x1="-100000"
y1="0"
x2="100000"
y2="0"
ng-attr-class="{{debug.hidden && 'NetworkUI--hidden' || 'NetworkUI--debug'}}" />
<line ng-attr-x1="0"
ng-attr-y1="-100000"
ng-attr-x2="0"
ng-attr-y2="100000"
<line x1="0"
y1="-100000"
x2="0"
y2="100000"
ng-attr-class="{{debug.hidden && 'NetworkUI--hidden' || 'NetworkUI--debug'}}" />
<rect ng-attr-x="{{view_port.x}}"
ng-attr-y="{{view_port.y}}"
ng-attr-width="{{view_port.width}}"
ng-attr-height="{{view_port.height}}"
ng-attr-class="{{debug.hidden && 'NetworkUI--hidden' || 'NetworkUI--debug'}}"
ng-attr-style="stroke-width: {{2 / current_scale}}"></rect>

View File

@ -1,4 +1,19 @@
<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-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>
<g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}"
@ -22,7 +37,7 @@
y="-52"
ng-attr-width="{{100 + 4}}"
ng-attr-height="{{100 + 4}}"
ng-attr-class="{{device.selected || device.remote_selected ? device.selected && device.remote_selected ? 'NetworkUI__rack--selected-conflict' : device.selected ? 'NetworkUI__rack--selected' : 'NetworkUI__rack--remote-selected' : 'NetworkUI--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'}}"
rx=10>
</rect>
<g class="NetworkUI__rack">
@ -60,12 +75,13 @@
<circle cx="30" cy="35" r=7 />
</circle>
</g>
<g ng-show="current_scale > 0.5">
<text ng-attr-class="{{device.selected && ! device.edit_label ? 'selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
text-anchor="middle"
x="0"
y="75"> {{device.name}} </text>
<text text-anchor="middle" x="0" y="75">{{device.name}}{{device.edit_label?'_':''}}</text>
</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>

View File

@ -0,0 +1,70 @@
<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>

View File

@ -1,5 +1,19 @@
<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">
<line ng-attr-x1="{{-50 - 10}}"
ng-attr-y1="0"
@ -22,7 +36,7 @@
cx="0"
cy="0"
ng-attr-r="{{50 + 2}}"
ng-attr-class="{{device.selected || device.remote_selected ? device.selected && device.remote_selected ? 'NetworkUI__router--selected-conflict' : device.selected ? 'NetworkUI__router--selected' : 'NetworkUI__router--remote-selected' : 'NetworkUI--hidden'}}">
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"
@ -52,12 +66,12 @@
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(270) translate(-22, -20) scale(2.0)"/>
</g>
</g>
<g ng-show="current_scale > 0.5">
<text ng-attr-class="{{device.selected && ! device.edit_label ? 'NetworkUI__router-text--selected' : 'NetworkUI--hidden'}}"
<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"> {{device.name}}</text>
<text class="NetworkUI__router-text" text-anchor="middle" x="0" y="0">{{device.name}}{{device.edit_label?'_':''}}</text>
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

@ -0,0 +1,90 @@
<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-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>
<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>

View File

@ -0,0 +1,71 @@
<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>
<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

@ -1,10 +1,10 @@
<g ng-if="device.working">
<path ng-attr-transform="translate({{-device.width}}, {{-device.height}}) rotate({{frame/3}})" class="NetworkUI__status-path" ng-attr-d="{{device.describeArc(0, 0, 10, 0, 270)}}"/>
<g ng-if="item.working">
<path ng-attr-transform="translate({{-item.width}}, {{-item.height}}) rotate({{frame/3}})" class="NetworkUI__status-path" ng-attr-d="{{item.describeArc(0, 0, 10, 0, 270)}}"/>
</g>
<g ng-if="!device.working">
<circle ng-attr-cx="{{-device.width}}"
ng-attr-cy="{{-device.height}}"
<g ng-if="!item.working">
<circle ng-attr-cx="{{-item.width}}"
ng-attr-cy="{{-item.height}}"
r=10
ng-attr-class="{{device.status === null ? 'NetworkUI--hidden' : device.status ? 'NetworkUI__status--pass': 'NetworkUI__status--fail'}}">
ng-attr-class="{{item.status === null ? 'NetworkUI--hidden' : item.status ? 'NetworkUI__status--pass': 'NetworkUI__status--fail'}}">
</circle>
</g>

View File

@ -0,0 +1,133 @@
<!-- Straight line -->
<g ng-if="!debug.hidden">
<line ng-attr-x1="{{stream.from_device.x}}"
ng-attr-y1="{{stream.from_device.y}}"
ng-attr-x2="{{stream.to_device !== null ? stream.to_device.x : scaledX}}"
ng-attr-y2="{{stream.to_device !== null ? stream.to_device.y : scaledY}}"
class="NetworkUI--debug"></line>
</g>
<g ng-if="stream.to_device === null">
<line ng-attr-x1="{{stream.from_device.x}}"
ng-attr-y1="{{stream.from_device.y}}"
ng-attr-x2="{{stream.to_device !== null ? stream.to_device.x : scaledX}}"
ng-attr-y2="{{stream.to_device !== null ? stream.to_device.y : scaledY}}"
class="NetworkUI__stream"></line>
</g>
<!-- End Straight line -->
<!-- Large arc -->
<g ng-if="stream.to_device !== null">
<g ng-if="stream.to_device !== stream.from_device">
<g ng-attr-transform="translate({{stream.from_device.x}},
{{stream.from_device.y}})
rotate({{stream.slope()}})">
<circle ng-if="!debug.hidden"
ng-attr-cx="{{-stream.length()/2}}"
ng-attr-cy="{{-stream.arc_offset2()}}"
r=10
class="NetworkUI__circle-debug" ></circle>
<path class="NetworkUI__stream--selected" ng-if="stream.to_device !== null && stream.selected" ng-attr-d="M0 0 A {{stream.arc_r2()}} {{stream.arc_r2()}} 0 0 0 {{-stream.length()}} 0"></path>
<path class="NetworkUI__stream" ng-if="stream.to_device !== null" ng-attr-d="M0 0 A {{stream.arc_r2()}} {{stream.arc_r2()}} 0 0 0 {{-stream.length()}} 0"></path>
<line ng-if="!debug.hidden"
ng-attr-x1="{{-stream.length()/2}}"
y1=0
ng-attr-x2="{{-stream.length()/2}}"
ng-attr-y2="{{-stream.arc_offset2()}}"
class="NetworkUI--debug"></line>
<g ng-attr-transform="rotate({{stream.start_arc_angle()}})
translate(-{{stream.from_device.size}}, 0)">
<circle ng-if="!debug.hidden"
ng-attr-cx="0"
ng-attr-cy="0"
r=10
class="NetworkUI__circle-debug" ></circle>
</g>
<rect ng-if="!debug.hidden"
ng-attr-x="{{-stream.length()}}"
ng-attr-y="{{-stream.arc_offset2()}}"
ng-attr-width="{{stream.length()}}"
ng-attr-height="{{stream.arc_offset2()}}"
class="NetworkUI--debug"></rect>
</g>
</g>
</g>
<!-- End Large arc -->
<!-- Debug -->
<g ng-if="stream.to_device !== null">
<g ng-if="stream.to_device !== stream.from_device">
<g ng-if="!debug.hidden && current_scale > 0.5">
<line ng-if="stream.to_device !== null"
ng-attr-x1="{{stream.perpendicular(scaledX, scaledY).x2}}"
ng-attr-y1="{{stream.perpendicular(scaledX, scaledY).y2}}"
ng-attr-x2="{{scaledX}}"
ng-attr-y2="{{scaledY}}"
ng-attr-class="NetworkUI--debug" />
<g ng-attr-transform="translate({{stream.to_device.x}},
{{stream.to_device.y}})
rotate({{stream.slope()}})
translate({{stream.length()/2}}, 0)">
</g>
<g ng-attr-transform="translate({{stream.to_device.x}},
{{stream.to_device.y}})
rotate({{stream.slope()}})
translate({{stream.to_device.size}}, 0)">
<circle ng-attr-cx="0"
ng-attr-cy="0"
r=10
class="NetworkUI__circle-debug" ></circle>
</g>
<g ng-attr-transform="translate({{stream.from_device.x}},
{{stream.from_device.y}})
rotate({{stream.slope()}})
translate({{-stream.from_device.size}}, 0)">
<circle ng-attr-cx="0"
ng-attr-cy="0"
r=10
class="NetworkUI__circle-debug" ></circle>
</g>
</g>
</g>
</g>
<!-- End Debug -->
<!-- Arrow -->
<g ng-if="stream.to_device !== stream.from_device">
<g ng-if="stream.to_device !== null" ng-attr-transform="translate({{stream.to_device.x}},
{{stream.to_device.y}})
rotate({{stream.slope()}})
rotate({{-stream.end_arc_angle()}})
translate({{stream.to_device.size}}, 0)
rotate({{stream.end_arc_angle()}})
rotate(180)
rotate({{-stream.arc_angle_tan2()}})">
<line ng-if="!debug.hidden"
x1=0
y1=0
x2=-100
y2=0
class="NetworkUI--debug"></line>
<g transform="translate(-19, -9)">
<path ng-attr-transform="translate(-2, -3)" d="M0,0 L0,24 L24,12 z" class="{{stream.selected && 'NetworkUI__stream--arrow-selected' || 'NetworkUI--hidden'}}"/>
<path d="M0,0 L0,18 L18,9 z" class="NetworkUI__stream-arrow"/>
</g>
</g>
<!-- End Arrow -->
<!-- Text -->
<g ng-if="current_scale > 0.5 && stream.to_device !== null"
ng-attr-transform="translate({{stream.from_device.x}},
{{stream.from_device.y}})
rotate({{stream.slope()}})
translate({{-stream.length()/2}}, 0)
translate(0, {{-stream.arc_offset2()}})
translate(0, -5)
rotate({{stream.flip_text_rotate()}})
translate(0, {{stream.flip_text_offset()}})
">
<text ng-attr-class="{{stream.selected && ! stream.edit_label ? 'NetworkUI__stream-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
text-anchor="middle"
x="0"
y="0"> {{stream.label}}</text>
<text class="NetworkUI__stream-text" text-anchor="middle" x="0" y="0">{{stream.label}}{{stream.edit_label?'_':''}}</text>
</g>
</g>
<!-- End Text -->

View File

@ -1,5 +1,19 @@
<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">
<line ng-attr-x1="{{-50 - 10}}"
ng-attr-y1="0"
@ -22,7 +36,7 @@
y="-52"
ng-attr-width="{{100 + 4}}"
ng-attr-height="{{100 + 4}}"
ng-attr-class="{{device.selected || device.remote_selected ? device.selected && device.remote_selected ? 'NetworkUI__switch--selected-conflict' : device.selected ? 'NetworkUI__switch--selected' : 'NetworkUI__switch--remote-selected' : 'NetworkUI--hidden'}}"
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">
@ -54,11 +68,11 @@
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="current_scale > 0.5">
<text ng-attr-class="{{device.selected && ! device.edit_label ? 'NetworkUI__switch-text--selected' : 'NetworkUI--hidden'}}"
<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"> {{device.name}} </text>
<text class="NetworkUI__switch-text" text-anchor="middle" x="0" y="0">{{device.name}}{{device.edit_label?'_':''}}</text>
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

@ -1,5 +1,5 @@
<g ng-attr-transform="translate({{-device.width}}, {{-device.height}})">
<g ng-repeat="task in device.tasks | limitTo: -7">
<g ng-attr-transform="translate({{-item.width}}, {{-item.height}})">
<g ng-repeat="task in item.tasks | limitTo: -7">
<g ng-if="task.working && current_scale > 0.5">
<path ng-attr-transform="translate({{$index * 12 + 17}}, -5 ) rotate({{frame/3}})" class="NetworkUI__status-path" ng-attr-d="{{task.describeArc(0, 0, 5, 0, 270)}}"/>
</g>