mirror of
https://github.com/ansible/awx.git
synced 2026-01-14 19:30:39 -03:30
* Fixes bug where new devices on the canvas weren't added to the search dropdown * Fixes bug with closing the details panel * Changes the fill color to white for remote-selected devices * Fixes read-only mode by swapping out move controller for move read-only * Updates range on the zoom widget
1463 lines
60 KiB
JavaScript
1463 lines
60 KiB
JavaScript
/* Copyright (c) 2017 Red Hat, Inc. */
|
|
var angular = require('angular');
|
|
var fsm = require('./fsm.js');
|
|
var mode_fsm = require('./mode.fsm.js');
|
|
var hotkeys = require('./hotkeys.fsm.js');
|
|
var toolbox_fsm = require('./toolbox.fsm.js');
|
|
var view = require('./view.fsm.js');
|
|
var move = require('./move.fsm.js');
|
|
var move_readonly = require('./move.readonly.fsm.js');
|
|
var buttons = require('./buttons.fsm.js');
|
|
var time = require('./time.fsm.js');
|
|
var test_fsm = require('./test.fsm.js');
|
|
var util = require('./util.js');
|
|
var models = require('./models.js');
|
|
var messages = require('./messages.js');
|
|
var animations = require('./animations.js');
|
|
var keybindings = require('./keybindings.fsm.js');
|
|
var details_panel_fsm = require('./details.panel.fsm.js');
|
|
var svg_crowbar = require('./vendor/svg-crowbar.js');
|
|
var ReconnectingWebSocket = require('reconnectingwebsocket');
|
|
|
|
var NetworkUIController = function($scope,
|
|
$document,
|
|
$location,
|
|
$window,
|
|
$http,
|
|
$q,
|
|
$state,
|
|
ProcessErrors,
|
|
ConfigService,
|
|
rbacUiControlService) {
|
|
|
|
window.scope = $scope;
|
|
|
|
$scope.http = $http;
|
|
|
|
$scope.api_token = '';
|
|
$scope.disconnected = false;
|
|
$scope.tests_enabled = false;
|
|
|
|
$scope.topology_id = 0;
|
|
// Create a web socket to connect to the backend server
|
|
|
|
$scope.inventory_id = $state.params.inventory_id;
|
|
|
|
var protocol = null;
|
|
|
|
if ($location.protocol() === 'http') {
|
|
protocol = 'ws';
|
|
} else if ($location.protocol() === 'https') {
|
|
protocol = 'wss';
|
|
}
|
|
|
|
$scope.initial_messages = [];
|
|
if (!$scope.disconnected) {
|
|
$scope.control_socket = new ReconnectingWebSocket(protocol + "://" + window.location.host + "/network_ui/topology?inventory_id=" + $scope.inventory_id,
|
|
null,
|
|
{debug: false, reconnectInterval: 300});
|
|
if ($scope.tests_enabled) {
|
|
$scope.test_socket = new ReconnectingWebSocket(protocol + "://" + window.location.host + "/network_ui/test?inventory_id=" + $scope.inventory_id,
|
|
null,
|
|
{debug: false, reconnectInterval: 300});
|
|
} else {
|
|
$scope.test_socket = {
|
|
on_message: util.noop,
|
|
send: util.noop
|
|
};
|
|
}
|
|
|
|
} else {
|
|
$scope.control_socket = {
|
|
on_message: util.noop
|
|
};
|
|
}
|
|
$scope.my_location = $location.protocol() + "://" + $location.host() + ':' + $location.port();
|
|
$scope.client_id = 0;
|
|
$scope.test_client_id = 0;
|
|
$scope.onMouseDownResult = "";
|
|
$scope.onMouseUpResult = "";
|
|
$scope.onMouseEnterResult = "";
|
|
$scope.onMouseLeaveResult = "";
|
|
$scope.onMouseMoveResult = "";
|
|
$scope.onMouseMoveResult = "";
|
|
$scope.current_scale = 1.0;
|
|
$scope.current_mode = null;
|
|
$scope.panX = 0;
|
|
$scope.panY = 0;
|
|
$scope.mouseX = 0;
|
|
$scope.mouseY = 0;
|
|
$scope.scaledX = 0;
|
|
$scope.scaledY = 0;
|
|
$scope.pressedX = 0;
|
|
$scope.pressedY = 0;
|
|
$scope.pressedScaledX = 0;
|
|
$scope.pressedScaledY = 0;
|
|
$scope.lastPanX = 0;
|
|
$scope.lastPanY = 0;
|
|
$scope.selected_devices = [];
|
|
$scope.selected_links = [];
|
|
$scope.selected_interfaces = [];
|
|
$scope.selected_items = [];
|
|
$scope.new_link = null;
|
|
$scope.new_stream = null;
|
|
$scope.last_key = "";
|
|
$scope.last_key_code = null;
|
|
$scope.last_event = null;
|
|
$scope.cursor = {'x':100, 'y': 100, 'hidden': true};
|
|
|
|
$scope.debug = {'hidden': true};
|
|
$scope.hide_buttons = false;
|
|
$scope.hide_menus = false;
|
|
$scope.hide_links = false;
|
|
$scope.hide_interfaces = false;
|
|
$scope.graph = {'width': window.innerWidth,
|
|
'right_column': 300,
|
|
'height': window.innerHeight};
|
|
$scope.MAX_ZOOM = 5;
|
|
$scope.MIN_ZOOM = 0.1;
|
|
$scope.device_id_seq = util.natural_numbers(0);
|
|
$scope.link_id_seq = util.natural_numbers(0);
|
|
$scope.message_id_seq = util.natural_numbers(0);
|
|
$scope.test_result_id_seq = util.natural_numbers(0);
|
|
$scope.animation_id_seq = util.natural_numbers(0);
|
|
$scope.overall_toolbox_collapsed = false;
|
|
$scope.time_pointer = -1;
|
|
$scope.frame = 0;
|
|
$scope.recording = false;
|
|
$scope.replay = false;
|
|
$scope.devices = [];
|
|
$scope.devices_by_name = {};
|
|
$scope.links = [];
|
|
$scope.links_in_vars_by_device = {};
|
|
$scope.tests = [];
|
|
$scope.current_tests = [];
|
|
$scope.current_test = null;
|
|
$scope.template_building = false;
|
|
$scope.version = null;
|
|
$scope.test_events = [];
|
|
$scope.test_results = [];
|
|
$scope.test_errors = [];
|
|
$scope.animations = [];
|
|
$scope.sequences = {};
|
|
$scope.view_port = {'x': 0,
|
|
'y': 0,
|
|
'width': 0,
|
|
'height': 0,
|
|
};
|
|
$scope.trace_id_seq = util.natural_numbers(0);
|
|
$scope.trace_order_seq = util.natural_numbers(0);
|
|
$scope.trace_id = $scope.trace_id_seq();
|
|
$scope.jump = {from_x: 0,
|
|
from_y: 0,
|
|
to_x: 0,
|
|
to_y: 0};
|
|
$scope.canEdit = $scope.$parent.$resolve.resolvedModels.canEdit;
|
|
$scope.send_trace_message = function (message) {
|
|
if (!$scope.recording) {
|
|
return;
|
|
}
|
|
message.sender = $scope.test_client_id;
|
|
message.trace_id = $scope.trace_id;
|
|
message.message_id = $scope.message_id_seq();
|
|
var data = messages.serialize(message);
|
|
if (!$scope.disconnected) {
|
|
try {
|
|
$scope.test_socket.send(data);
|
|
}
|
|
catch(err) {
|
|
$scope.initial_messages.push(message);
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.onKeyDown = function ($event) {
|
|
if ($scope.recording) {
|
|
$scope.send_test_message(new messages.KeyEvent($scope.test_client_id,
|
|
$event.key,
|
|
$event.keyCode,
|
|
$event.type,
|
|
$event.altKey,
|
|
$event.shiftKey,
|
|
$event.ctrlKey,
|
|
$event.metaKey,
|
|
$scope.trace_id));
|
|
}
|
|
$scope.last_event = $event;
|
|
$scope.last_key = $event.key;
|
|
$scope.last_key_code = $event.keyCode;
|
|
$scope.first_channel.send('KeyDown', $event);
|
|
$scope.$apply();
|
|
$event.preventDefault();
|
|
};
|
|
|
|
//Define the FSMs
|
|
$scope.hotkeys_controller = new fsm.FSMController($scope, "hotkeys_fsm", hotkeys.Start, $scope);
|
|
$scope.keybindings_controller = new fsm.FSMController($scope, "keybindings_fsm", keybindings.Start, $scope);
|
|
$scope.view_controller = new fsm.FSMController($scope, "view_fsm", view.Start, $scope);
|
|
$scope.move_controller = new fsm.FSMController($scope, "move_fsm", move.Start, $scope);
|
|
$scope.move_readonly_controller = new fsm.FSMController($scope, "move_readonly_fsm", move_readonly.Start, $scope);
|
|
$scope.details_panel_controller = new fsm.FSMController($scope, "details_panel_fsm", details_panel_fsm.Start, $scope);
|
|
$scope.buttons_controller = new fsm.FSMController($scope, "buttons_fsm", buttons.Start, $scope);
|
|
$scope.time_controller = new fsm.FSMController($scope, "time_fsm", time.Start, $scope);
|
|
$scope.test_controller = new fsm.FSMController($scope, "test_fsm", test_fsm.Start, $scope);
|
|
|
|
$scope.inventory_toolbox_controller = new fsm.FSMController($scope, "toolbox_fsm", toolbox_fsm.Start, $scope);
|
|
|
|
var toolboxTopMargin = $('.Networking-top').height();
|
|
var toolboxTitleMargin = toolboxTopMargin + 35;
|
|
var toolboxHeight = $scope.graph.height - $('.Networking-top').height();
|
|
|
|
$scope.update_links_in_vars_by_device = function (device_name, variables) {
|
|
|
|
var j = 0;
|
|
var link = null;
|
|
|
|
if (variables.ansible_topology !== undefined) {
|
|
if (variables.ansible_topology.links !== undefined) {
|
|
for (j=0; j < variables.ansible_topology.links.length; j++) {
|
|
link = variables.ansible_topology.links[j];
|
|
if (link.remote_device_name !== undefined &&
|
|
link.remote_interface_name !== undefined &&
|
|
link.name !== undefined) {
|
|
if ($scope.links_in_vars_by_device[device_name] === undefined) {
|
|
$scope.links_in_vars_by_device[device_name] = [];
|
|
}
|
|
if ($scope.links_in_vars_by_device[link.remote_device_name] === undefined) {
|
|
$scope.links_in_vars_by_device[link.remote_device_name] = [];
|
|
}
|
|
$scope.links_in_vars_by_device[device_name].push({
|
|
from_interface: link.name,
|
|
to_interface: link.remote_interface_name,
|
|
from_device: device_name,
|
|
to_device: link.remote_device_name
|
|
});
|
|
$scope.links_in_vars_by_device[link.remote_device_name].push({
|
|
from_interface: link.remote_interface_name,
|
|
to_interface: link.name,
|
|
from_device: link.remote_device_name,
|
|
to_device: device_name
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.for_each_page = function(url, callback, limit) {
|
|
|
|
function rec(url, rec_limit) {
|
|
if (rec_limit <= 0) {
|
|
return;
|
|
}
|
|
$http.get(url)
|
|
.then(function(response) {
|
|
callback(response.data.results);
|
|
if (response.data.next) {
|
|
rec(response.data.next, rec_limit-1);
|
|
}
|
|
})
|
|
.catch(({data, status}) => {
|
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get host data: ' + status });
|
|
});
|
|
}
|
|
rec(url, limit);
|
|
};
|
|
|
|
//Inventory Toolbox Setup
|
|
$scope.inventory_toolbox = new models.ToolBox(0, 'Inventory', 'device', 0, toolboxTopMargin, 200, toolboxHeight);
|
|
if (!$scope.disconnected) {
|
|
$scope.for_each_page('/api/v2/inventories/' + $scope.inventory_id + '/hosts/',
|
|
function(all_results) {
|
|
let hosts = all_results;
|
|
console.log(hosts.length);
|
|
for(var i = 0; i<hosts.length; i++) {
|
|
console.log(i);
|
|
try {
|
|
let device_type = null;
|
|
let device_name = null;
|
|
let device = null;
|
|
let host = hosts[i];
|
|
device_name = host.name;
|
|
console.log(device_name);
|
|
if (host.variables !== "") {
|
|
host.data = jsyaml.safeLoad(host.variables);
|
|
console.log(host.data);
|
|
} else {
|
|
host.data = {};
|
|
}
|
|
if (host.data.ansible_topology === undefined) {
|
|
device_type = 'unknown';
|
|
} else {
|
|
if (host.data.ansible_topology.type === undefined) {
|
|
device_type = 'unknown';
|
|
} else {
|
|
device_type = host.data.ansible_topology.type;
|
|
}
|
|
|
|
$scope.update_links_in_vars_by_device(device_name, host.data);
|
|
}
|
|
if ($scope.devices_by_name[device_name] === undefined) {
|
|
console.log(['adding', device_name]);
|
|
device = new models.Device(0, device_name, 0, 0, device_type, host.id);
|
|
device.icon = true;
|
|
device.variables = host.data;
|
|
$scope.inventory_toolbox.items.push(device);
|
|
}
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
}
|
|
}, 100);
|
|
}
|
|
$scope.inventory_toolbox.spacing = 150;
|
|
$scope.inventory_toolbox.enabled = true;
|
|
$scope.inventory_toolbox.title_coordinates = {x: 60, y: toolboxTitleMargin};
|
|
$scope.inventory_toolbox_controller.toolbox = $scope.inventory_toolbox;
|
|
$scope.inventory_toolbox_controller.remove_on_drop = true;
|
|
$scope.inventory_toolbox_controller.debug = true;
|
|
$scope.inventory_toolbox_controller.dropped_action = function (selected_item) {
|
|
$scope.first_channel.send("PasteDevice", new messages.PasteDevice(selected_item));
|
|
};
|
|
|
|
//End Inventory Toolbox Setup
|
|
|
|
$scope.mode_controller = new fsm.FSMController($scope, "mode_fsm", mode_fsm.Start, $scope);
|
|
|
|
//Wire up the FSMs
|
|
$scope.keybindings_controller.delegate_channel = new fsm.Channel($scope.keybindings_controller,
|
|
$scope.hotkeys_controller,
|
|
$scope);
|
|
|
|
$scope.view_controller.delegate_channel = new fsm.Channel($scope.view_controller,
|
|
$scope.keybindings_controller,
|
|
$scope);
|
|
if ($scope.canEdit) {
|
|
$scope.move_controller.delegate_channel = new fsm.Channel($scope.move_controller,
|
|
$scope.view_controller,
|
|
$scope);
|
|
$scope.details_panel_controller.delegate_channel = new fsm.Channel($scope.details_panel_controller,
|
|
$scope.move_controller,
|
|
$scope);
|
|
} else {
|
|
$scope.move_readonly_controller.delegate_channel = new fsm.Channel($scope.move_readonly_controller,
|
|
$scope.view_controller,
|
|
$scope);
|
|
$scope.details_panel_controller.delegate_channel = new fsm.Channel($scope.details_panel_controller,
|
|
$scope.move_readonly_controller,
|
|
$scope);
|
|
}
|
|
if ($scope.canEdit) {
|
|
$scope.inventory_toolbox_controller.delegate_channel = new fsm.Channel($scope.inventory_toolbox_controller,
|
|
$scope.details_panel_controller,
|
|
$scope);
|
|
$scope.buttons_controller.delegate_channel = new fsm.Channel($scope.buttons_controller,
|
|
$scope.inventory_toolbox_controller,
|
|
$scope);
|
|
} else {
|
|
$scope.buttons_controller.delegate_channel = new fsm.Channel($scope.buttons_controller,
|
|
$scope.details_panel_controller,
|
|
$scope);
|
|
}
|
|
$scope.time_controller.delegate_channel = new fsm.Channel($scope.time_controller,
|
|
$scope.buttons_controller,
|
|
$scope);
|
|
$scope.mode_controller.delegate_channel = new fsm.Channel($scope.mode_controller,
|
|
$scope.time_controller,
|
|
$scope);
|
|
$scope.test_controller.delegate_channel = new fsm.Channel($scope.test_controller,
|
|
$scope.mode_controller,
|
|
$scope);
|
|
|
|
|
|
$scope.first_channel = new fsm.Channel(null,
|
|
$scope.mode_controller,
|
|
$scope);
|
|
|
|
$scope.test_channel = new fsm.Channel(null,
|
|
$scope.test_controller,
|
|
$scope);
|
|
|
|
var getMouseEventResult = function (mouseEvent) {
|
|
return "(" + mouseEvent.x + ", " + mouseEvent.y + ")";
|
|
};
|
|
|
|
$scope.updateScaledXY = function() {
|
|
if (isNaN($scope.mouseX) ||
|
|
isNaN($scope.mouseY) ||
|
|
isNaN($scope.panX) ||
|
|
isNaN($scope.panY) ||
|
|
isNaN($scope.current_scale)) {
|
|
return;
|
|
}
|
|
$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() {
|
|
if (isNaN($scope.panX) ||
|
|
isNaN($scope.panY) ||
|
|
isNaN($scope.current_scale)) {
|
|
return;
|
|
}
|
|
var g = document.getElementById('frame_g');
|
|
g.setAttribute('transform','translate(' + $scope.panX + ',' + $scope.panY + ') scale(' + $scope.current_scale + ')');
|
|
};
|
|
|
|
$scope.to_virtual_coordinates = function (b_x, b_y) {
|
|
var v_x = (b_x - $scope.panX) / $scope.current_scale;
|
|
var v_y = (b_y - $scope.panY) / $scope.current_scale;
|
|
return {x: v_x, y: v_y};
|
|
};
|
|
|
|
$scope.to_pan = function (v_x, v_y) {
|
|
var p_x = v_x * $scope.current_scale * -1;
|
|
var p_y = v_y * $scope.current_scale * -1;
|
|
return {x: p_x, y: p_y};
|
|
};
|
|
|
|
$scope.clear_selections = function () {
|
|
|
|
var i = 0;
|
|
var j = 0;
|
|
var devices = $scope.devices;
|
|
var links = $scope.links;
|
|
$scope.selected_items = [];
|
|
$scope.selected_devices = [];
|
|
$scope.selected_links = [];
|
|
$scope.selected_interfaces = [];
|
|
for (i = 0; i < links.length; i++) {
|
|
if (links[i].selected) {
|
|
$scope.send_control_message(new messages.LinkUnSelected($scope.client_id, links[i].id));
|
|
}
|
|
links[i].selected = false;
|
|
}
|
|
for (i = 0; i < devices.length; i++) {
|
|
for (j = 0; j < devices[i].interfaces.length; j++) {
|
|
devices[i].interfaces[j].selected = false;
|
|
}
|
|
if (devices[i].selected) {
|
|
$scope.send_control_message(new messages.DeviceUnSelected($scope.client_id, devices[i].id));
|
|
}
|
|
devices[i].selected = false;
|
|
}
|
|
};
|
|
|
|
$scope.select_items = function (multiple_selection) {
|
|
|
|
var i = 0;
|
|
var j = 0;
|
|
var devices = $scope.devices;
|
|
var last_selected_device = null;
|
|
var last_selected_interface = null;
|
|
var last_selected_link = null;
|
|
|
|
$scope.pressedX = $scope.mouseX;
|
|
$scope.pressedY = $scope.mouseY;
|
|
$scope.pressedScaledX = $scope.scaledX;
|
|
$scope.pressedScaledY = $scope.scaledY;
|
|
|
|
if (!multiple_selection) {
|
|
$scope.clear_selections();
|
|
}
|
|
|
|
for (i = devices.length - 1; i >= 0; i--) {
|
|
if (devices[i].is_selected($scope.scaledX, $scope.scaledY)) {
|
|
devices[i].selected = true;
|
|
$scope.send_control_message(new messages.DeviceSelected($scope.client_id, devices[i].id));
|
|
last_selected_device = devices[i];
|
|
if ($scope.selected_items.indexOf($scope.devices[i]) === -1) {
|
|
$scope.selected_items.push($scope.devices[i]);
|
|
}
|
|
if ($scope.selected_devices.indexOf(devices[i]) === -1) {
|
|
$scope.selected_devices.push(devices[i]);
|
|
}
|
|
if (!multiple_selection) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Do not select interfaces if a device was selected
|
|
if (last_selected_device === null && !$scope.hide_interfaces) {
|
|
for (i = devices.length - 1; i >= 0; i--) {
|
|
for (j = devices[i].interfaces.length - 1; j >= 0; j--) {
|
|
if (devices[i].interfaces[j].is_selected($scope.scaledX, $scope.scaledY)) {
|
|
devices[i].interfaces[j].selected = true;
|
|
last_selected_interface = devices[i].interfaces[j];
|
|
if ($scope.selected_interfaces.indexOf($scope.devices[i].interfaces[j]) === -1) {
|
|
$scope.selected_interfaces.push($scope.devices[i].interfaces[j]);
|
|
}
|
|
if ($scope.selected_items.indexOf($scope.devices[i].interfaces[j]) === -1) {
|
|
$scope.selected_items.push($scope.devices[i].interfaces[j]);
|
|
}
|
|
if (!multiple_selection) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Do not select links if a device was selected
|
|
if (last_selected_device === null && last_selected_interface === null) {
|
|
for (i = $scope.links.length - 1; i >= 0; i--) {
|
|
if ($scope.links[i].is_selected($scope.scaledX, $scope.scaledY)) {
|
|
$scope.links[i].selected = true;
|
|
$scope.send_control_message(new messages.LinkSelected($scope.client_id, $scope.links[i].id));
|
|
last_selected_link = $scope.links[i];
|
|
if ($scope.selected_items.indexOf($scope.links[i]) === -1) {
|
|
$scope.selected_items.push($scope.links[i]);
|
|
}
|
|
if ($scope.selected_links.indexOf($scope.links[i]) === -1) {
|
|
$scope.selected_links.push($scope.links[i]);
|
|
if (!multiple_selection) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return {last_selected_device: last_selected_device,
|
|
last_selected_link: last_selected_link,
|
|
last_selected_interface: last_selected_interface,
|
|
};
|
|
};
|
|
|
|
// Event Handlers
|
|
|
|
$scope.normalize_mouse_event = function ($event) {
|
|
if ($event.pageX !== undefined) {
|
|
$event.x = $event.pageX;
|
|
}
|
|
if ($event.pageY !== undefined) {
|
|
$event.y = $event.pageY;
|
|
}
|
|
if ($event.originalEvent !== undefined) {
|
|
var originalEvent = $event.originalEvent;
|
|
if (originalEvent.wheelDelta !== undefined) {
|
|
$event.delta = $event.originalEvent.wheelDelta;
|
|
}
|
|
if (originalEvent.wheelDeltaX !== undefined) {
|
|
$event.deltaX = $event.originalEvent.wheelDeltaX;
|
|
}
|
|
if (originalEvent.wheelDeltaY !== undefined) {
|
|
$event.deltaY = $event.originalEvent.wheelDeltaY;
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.onMouseDown = function ($event) {
|
|
$scope.normalize_mouse_event($event);
|
|
if ($scope.recording) {
|
|
$scope.send_test_message(new messages.MouseEvent($scope.test_client_id, $event.x, $event.y, $event.type, $scope.trace_id));
|
|
}
|
|
$scope.last_event = $event;
|
|
$scope.first_channel.send('MouseDown', $event);
|
|
$scope.onMouseDownResult = getMouseEventResult($event);
|
|
$event.preventDefault();
|
|
};
|
|
|
|
$scope.onMouseUp = function ($event) {
|
|
$scope.normalize_mouse_event($event);
|
|
if ($scope.recording) {
|
|
$scope.send_test_message(new messages.MouseEvent($scope.test_client_id, $event.x, $event.y, $event.type, $scope.trace_id));
|
|
}
|
|
$scope.last_event = $event;
|
|
$scope.first_channel.send('MouseUp', $event);
|
|
$scope.onMouseUpResult = getMouseEventResult($event);
|
|
$event.preventDefault();
|
|
};
|
|
|
|
$scope.onMouseLeave = function ($event) {
|
|
$scope.normalize_mouse_event($event);
|
|
if ($scope.recording) {
|
|
$scope.send_test_message(new messages.MouseEvent($scope.test_client_id, $event.x, $event.y, $event.type, $scope.trace_id));
|
|
}
|
|
$scope.onMouseLeaveResult = getMouseEventResult($event);
|
|
$event.preventDefault();
|
|
};
|
|
|
|
$scope.onMouseMove = function ($event) {
|
|
$scope.normalize_mouse_event($event);
|
|
if ($scope.recording) {
|
|
$scope.send_test_message(new messages.MouseEvent($scope.test_client_id, $event.x, $event.y, $event.type, $scope.trace_id));
|
|
}
|
|
//var coords = getCrossBrowserElementCoords($event);
|
|
$scope.cursor.x = $event.x;
|
|
$scope.cursor.y = $event.y;
|
|
$scope.mouseX = $event.x;
|
|
$scope.mouseY = $event.y;
|
|
$scope.updateScaledXY();
|
|
$scope.first_channel.send('MouseMove', $event);
|
|
$scope.onMouseMoveResult = getMouseEventResult($event);
|
|
$event.preventDefault();
|
|
};
|
|
|
|
$scope.onMouseOver = function ($event) {
|
|
$scope.normalize_mouse_event($event);
|
|
if ($scope.recording) {
|
|
$scope.send_test_message(new messages.MouseEvent($scope.test_client_id, $event.x, $event.y, $event.type, $scope.trace_id));
|
|
}
|
|
$scope.onMouseOverResult = getMouseEventResult($event);
|
|
$event.preventDefault();
|
|
};
|
|
|
|
$scope.onMouseEnter = $scope.onMouseOver;
|
|
|
|
$scope.onMouseWheel = function ($event) {
|
|
$scope.normalize_mouse_event($event);
|
|
var delta = $event.delta;
|
|
var deltaX = $event.deltaX;
|
|
var deltaY = $event.deltaY;
|
|
if ($scope.recording) {
|
|
$scope.send_test_message(new messages.MouseWheelEvent($scope.test_client_id, delta, deltaX, deltaY, $event.type, $event.originalEvent.metaKey, $scope.trace_id));
|
|
}
|
|
$scope.last_event = $event;
|
|
$scope.first_channel.send('MouseWheel', [$event, delta, deltaX, deltaY]);
|
|
$event.preventDefault();
|
|
};
|
|
|
|
// Conext Menu Button Handlers
|
|
$scope.removeContextMenu = function(){
|
|
let context_menu = $scope.context_menus[0];
|
|
context_menu.enabled = false;
|
|
context_menu.x = -100000;
|
|
context_menu.y = -100000;
|
|
context_menu.buttons.forEach(function(button){
|
|
button.enabled = false;
|
|
button.x = -100000;
|
|
button.y = -100000;
|
|
});
|
|
};
|
|
|
|
$scope.closeDetailsPanel = function () {
|
|
$scope.first_channel.send('DetailsPanelClose', {});
|
|
};
|
|
|
|
$scope.$on('awxNet-closeDetailsPanel', $scope.closeDetailsPanel);
|
|
|
|
$scope.onDetailsContextButton = function () {
|
|
function emitCallback(item, canAdd){
|
|
$scope.first_channel.send('DetailsPanel', {});
|
|
$scope.removeContextMenu();
|
|
$scope.update_toolbox_heights();
|
|
$scope.$emit('awxNet-showDetails', item, canAdd);
|
|
}
|
|
|
|
// show details for devices
|
|
if ($scope.selected_devices.length === 1 && $scope.selected_devices[0].host_id === 0){
|
|
// following block is intended for devices added in the network UI but not in Tower
|
|
emitCallback($scope.selected_devices[0]);
|
|
}
|
|
|
|
// following block is intended for devices that are saved in the API
|
|
if ($scope.selected_devices.length === 1 && $scope.selected_devices[0].host_id !== 0){
|
|
let host_id = $scope.selected_devices[0].host_id;
|
|
let url = `/api/v2/hosts/${host_id}/`;
|
|
let hostData = $http.get(url)
|
|
.then(function(response) {
|
|
let host = response.data;
|
|
host.host_id = host.id;
|
|
return host;
|
|
})
|
|
.catch(({data, status}) => {
|
|
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get host data: ' + status });
|
|
});
|
|
let canAdd = rbacUiControlService.canAdd('hosts')
|
|
.then(function(res) {
|
|
return res.canAdd;
|
|
})
|
|
.catch(function() {
|
|
return false;
|
|
});
|
|
Promise.all([hostData, canAdd]).then((values) => {
|
|
let item = values[0];
|
|
let canAdd = values[1];
|
|
emitCallback(item, canAdd);
|
|
});
|
|
}
|
|
|
|
// show details for interfaces
|
|
else if($scope.selected_interfaces.length === 1){
|
|
emitCallback($scope.selected_interfaces[0]);
|
|
}
|
|
|
|
// show details for links
|
|
else if($scope.selected_links.length === 1){
|
|
emitCallback($scope.selected_links[0]);
|
|
}
|
|
|
|
};
|
|
|
|
$scope.onDeviceDestroy = function(data) {
|
|
$scope.destroy_device(data);
|
|
};
|
|
|
|
$scope.destroy_device = function(data) {
|
|
|
|
// Delete the device and any links connecting to the device.
|
|
var i = 0;
|
|
var j = 0;
|
|
var dindex = -1;
|
|
var lindex = -1;
|
|
var devices = $scope.devices.slice();
|
|
var all_links = $scope.links.slice();
|
|
for (i = 0; i < devices.length; i++) {
|
|
if (devices[i].id === data.id) {
|
|
dindex = $scope.devices.indexOf(devices[i]);
|
|
if (dindex !== -1) {
|
|
$scope.devices.splice(dindex, 1);
|
|
}
|
|
lindex = -1;
|
|
for (j = 0; j < all_links.length; j++) {
|
|
if (all_links[j].to_device === devices[i] ||
|
|
all_links[j].from_device === devices[i]) {
|
|
lindex = $scope.links.indexOf(all_links[j]);
|
|
if (lindex !== -1) {
|
|
$scope.links.splice(lindex, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.deleteDevice = function(){
|
|
var i = 0;
|
|
var j = 0;
|
|
var index = -1;
|
|
var devices = $scope.selected_devices;
|
|
var all_links = $scope.links.slice();
|
|
$scope.selected_devices = [];
|
|
$scope.selected_links = [];
|
|
$scope.move_controller.changeState(move.Ready);
|
|
for (i = 0; i < devices.length; i++) {
|
|
index = $scope.devices.indexOf(devices[i]);
|
|
if (index !== -1) {
|
|
$scope.devices.splice(index, 1);
|
|
$scope.devices_by_name[devices[i].name] = undefined;
|
|
$scope.$emit('awxNet-removeSearchOption', devices[i]);
|
|
devices[i].x = 0;
|
|
devices[i].y = 0;
|
|
devices[i].selected = false;
|
|
devices[i].remote_selected = false;
|
|
devices[i].interfaces = [];
|
|
devices[i].interfaces_by_name = [];
|
|
$scope.inventory_toolbox.items.push(devices[i]);
|
|
$scope.send_control_message(new messages.DeviceDestroy($scope.client_id,
|
|
devices[i].id,
|
|
devices[i].x,
|
|
devices[i].y,
|
|
devices[i].name,
|
|
devices[i].type,
|
|
devices[i].host_id));
|
|
}
|
|
for (j = 0; j < all_links.length; j++) {
|
|
if (all_links[j].to_device === devices[i] ||
|
|
all_links[j].from_device === devices[i]) {
|
|
index = $scope.links.indexOf(all_links[j]);
|
|
if (index !== -1) {
|
|
$scope.links.splice(index, 1);
|
|
$scope.send_control_message(new messages.LinkDestroy($scope.client_id,
|
|
all_links[j].id,
|
|
all_links[j].from_device.id,
|
|
all_links[j].to_device.id,
|
|
all_links[j].from_interface.id,
|
|
all_links[j].to_interface.id,
|
|
all_links[j].name));
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.onDeleteContextMenu = function(){
|
|
$scope.removeContextMenu();
|
|
if($scope.selected_devices.length === 1){
|
|
$scope.deleteDevice();
|
|
}
|
|
};
|
|
|
|
$scope.$on('awxNet-hideToolbox', () => {
|
|
$scope.first_channel.send("ToggleToolbox", {});
|
|
$scope.overall_toolbox_collapsed = !$scope.overall_toolbox_collapsed;
|
|
});
|
|
|
|
$scope.$on('awxNet-toolbarButtonEvent', function(e, functionName){
|
|
$scope[`on${functionName}Button`]();
|
|
});
|
|
|
|
$scope.$on('awxNet-SearchDropdown', function(){
|
|
$scope.first_channel.send('SearchDropdown', {});
|
|
});
|
|
|
|
$scope.$on('awxNet-SearchDropdownClose', function(){
|
|
$scope.first_channel.send('SearchDropdownClose', {});
|
|
});
|
|
|
|
$scope.$on('awxNet-search', function(e, device){
|
|
|
|
var searched;
|
|
for(var i = 0; i < $scope.devices.length; i++){
|
|
if(Number(device.id) === $scope.devices[i].id){
|
|
searched = $scope.devices[i];
|
|
}
|
|
}
|
|
searched.selected = true;
|
|
$scope.selected_devices.push(searched);
|
|
$scope.jump_to_animation(searched.x, searched.y, 1.0);
|
|
});
|
|
|
|
$scope.jump_to_animation = function(jump_to_x, jump_to_y, jump_to_scale, updateZoom) {
|
|
$scope.cancel_animations();
|
|
var v_center = $scope.to_virtual_coordinates($scope.graph.width/2, $scope.graph.height/2);
|
|
$scope.jump.from_x = v_center.x;
|
|
$scope.jump.from_y = v_center.y;
|
|
$scope.jump.to_x = jump_to_x;
|
|
$scope.jump.to_y = jump_to_y;
|
|
var distance = util.distance(v_center.x, v_center.y, jump_to_x, jump_to_y);
|
|
var num_frames = 30 * Math.floor((1 + 4 * distance / (distance + 3000)));
|
|
var scale_animation = new models.Animation($scope.animation_id_seq(),
|
|
num_frames,
|
|
{
|
|
c: -0.1,
|
|
distance: distance,
|
|
end_height: (1.0/jump_to_scale) - 1,
|
|
current_scale: $scope.current_scale,
|
|
scope: $scope,
|
|
updateZoomBoolean: updateZoom
|
|
},
|
|
$scope,
|
|
$scope,
|
|
animations.scale_animation);
|
|
$scope.animations.push(scale_animation);
|
|
var pan_animation = new models.Animation($scope.animation_id_seq(),
|
|
num_frames,
|
|
{
|
|
x2: jump_to_x,
|
|
y2: jump_to_y,
|
|
x1: v_center.x,
|
|
y1: v_center.y,
|
|
scope: $scope
|
|
},
|
|
$scope,
|
|
$scope,
|
|
animations.pan_animation);
|
|
$scope.animations.push(pan_animation);
|
|
};
|
|
|
|
$scope.$on('awxNet-zoom', (e, zoomPercent) => {
|
|
let v_center = $scope.to_virtual_coordinates($scope.graph.width/2, $scope.graph.height/2);
|
|
let scale = Math.pow(10, (zoomPercent - 120) / 120);
|
|
$scope.jump_to_animation(v_center.x, v_center.y, scale, false);
|
|
});
|
|
|
|
$scope.onRecordButton = function () {
|
|
$scope.recording = ! $scope.recording;
|
|
if ($scope.recording) {
|
|
$scope.trace_id = $scope.trace_id_seq();
|
|
$scope.send_test_message(new messages.MultipleMessage($scope.test_client_id,
|
|
[new messages.StartRecording($scope.test_client_id, $scope.trace_id),
|
|
new messages.ViewPort($scope.test_client_id,
|
|
$scope.current_scale,
|
|
$scope.panX,
|
|
$scope.panY,
|
|
$scope.graph.width,
|
|
$scope.graph.height,
|
|
$scope.trace_id),
|
|
new messages.Snapshot($scope.test_client_id,
|
|
$scope.devices,
|
|
$scope.links,
|
|
$scope.inventory_toolbox.items,
|
|
0,
|
|
$scope.trace_id)]));
|
|
} else {
|
|
$scope.send_test_message(new messages.MultipleMessage($scope.test_client_id,
|
|
[new messages.Snapshot($scope.test_client_id,
|
|
$scope.devices,
|
|
$scope.links,
|
|
$scope.inventory_toolbox.items,
|
|
1,
|
|
$scope.trace_id),
|
|
new messages.StopRecording($scope.test_client_id, $scope.trace_id)]));
|
|
}
|
|
};
|
|
|
|
$scope.onExportButton = function () {
|
|
$scope.cursor.hidden = true;
|
|
$scope.debug.hidden = true;
|
|
$scope.hide_buttons = true;
|
|
$scope.hide_menus = true;
|
|
setTimeout(function () {
|
|
svg_crowbar.svg_crowbar();
|
|
$scope.cursor.hidden = false;
|
|
$scope.hide_buttons = false;
|
|
$scope.hide_menus = false;
|
|
$scope.$apply();
|
|
}, 1000);
|
|
};
|
|
|
|
$scope.onExportYamlButton = function () {
|
|
$window.open('/network_ui/topology.yaml?topology_id=' + $scope.topology_id , '_blank');
|
|
};
|
|
|
|
// Context Menu Buttons
|
|
const contextMenuButtonHeight = 26;
|
|
let contextMenuHeight = 64;
|
|
$scope.context_menu_buttons = [
|
|
new models.ContextMenuButton("Details", 236, 231, 160, contextMenuButtonHeight, $scope.onDetailsContextButton, $scope),
|
|
new models.ContextMenuButton("Remove", 256, 231, 160, contextMenuButtonHeight, $scope.onDeleteContextMenu, $scope)
|
|
];
|
|
if(!$scope.canEdit){
|
|
$scope.context_menu_buttons.pop();
|
|
contextMenuHeight = $scope.context_menu_buttons.length * contextMenuButtonHeight + 12;
|
|
}
|
|
// Context Menus
|
|
$scope.context_menus = [
|
|
new models.ContextMenu('HOST', 210, 200, 160, contextMenuHeight, $scope.contextMenuCallback, false, $scope.context_menu_buttons, $scope)
|
|
];
|
|
|
|
$scope.onDownloadTraceButton = function () {
|
|
window.open("/network_ui_test/download_trace?topology_id=" + $scope.topology_id + "&trace_id=" + $scope.trace_id + "&client_id=" + $scope.test_client_id);
|
|
};
|
|
|
|
$scope.onDownloadRecordingButton = function () {
|
|
window.open("/network_ui_test/download_recording?topology_id=" + $scope.topology_id + "&trace_id=" + $scope.trace_id + "&client_id=" + $scope.test_client_id);
|
|
};
|
|
|
|
$scope.onUploadTestButton = function () {
|
|
window.open("/network_ui_test/upload_test", "_top");
|
|
};
|
|
|
|
$scope.onRunTestsButton = function () {
|
|
|
|
$scope.test_results = [];
|
|
$scope.current_tests = $scope.tests.slice();
|
|
$scope.test_channel.send("EnableTest", new messages.EnableTest());
|
|
};
|
|
|
|
$scope.all_buttons = $scope.context_menu_buttons;
|
|
|
|
$scope.onDeviceCreate = function(data) {
|
|
$scope.create_device(data);
|
|
};
|
|
|
|
$scope.create_device = function(data) {
|
|
console.log(data);
|
|
var device = new models.Device(data.id,
|
|
data.name,
|
|
data.x,
|
|
data.y,
|
|
data.type,
|
|
data.host_id);
|
|
$scope.device_id_seq = util.natural_numbers(data.id);
|
|
$scope.devices.push(device);
|
|
$scope.devices_by_name[device.name] = device;
|
|
};
|
|
|
|
$scope.onInterfaceCreate = function(data) {
|
|
$scope.create_interface(data);
|
|
};
|
|
|
|
$scope.create_interface = function(data) {
|
|
var i = 0;
|
|
var new_interface = new models.Interface(data.id, data.name);
|
|
for (i = 0; i < $scope.devices.length; i++){
|
|
if ($scope.devices[i].id === data.device_id) {
|
|
$scope.devices[i].interface_seq = util.natural_numbers(data.id);
|
|
new_interface.device = $scope.devices[i];
|
|
$scope.devices[i].interfaces.push(new_interface);
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.onLinkCreate = function(data) {
|
|
console.log(data);
|
|
$scope.create_link(data);
|
|
};
|
|
|
|
$scope.create_link = function(data) {
|
|
var i = 0;
|
|
var j = 0;
|
|
var new_link = new models.Link(null, null, null, null);
|
|
new_link.id = data.id;
|
|
$scope.link_id_seq = util.natural_numbers(data.id);
|
|
for (i = 0; i < $scope.devices.length; i++){
|
|
if ($scope.devices[i].id === data.from_device_id) {
|
|
new_link.from_device = $scope.devices[i];
|
|
for (j = 0; j < $scope.devices[i].interfaces.length; j++){
|
|
if ($scope.devices[i].interfaces[j].id === data.from_interface_id) {
|
|
new_link.from_interface = $scope.devices[i].interfaces[j];
|
|
$scope.devices[i].interfaces[j].link = new_link;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < $scope.devices.length; i++){
|
|
if ($scope.devices[i].id === data.to_device_id) {
|
|
new_link.to_device = $scope.devices[i];
|
|
for (j = 0; j < $scope.devices[i].interfaces.length; j++){
|
|
if ($scope.devices[i].interfaces[j].id === data.to_interface_id) {
|
|
new_link.to_interface = $scope.devices[i].interfaces[j];
|
|
$scope.devices[i].interfaces[j].link = new_link;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
console.log(new_link);
|
|
if (new_link.from_interface !== null && new_link.to_interface !== null) {
|
|
new_link.from_interface.dot();
|
|
new_link.to_interface.dot();
|
|
}
|
|
if (new_link.from_device !== null && new_link.to_device !== null) {
|
|
$scope.links.push(new_link);
|
|
}
|
|
};
|
|
|
|
$scope.onLinkDestroy = function(data) {
|
|
$scope.destroy_link(data);
|
|
};
|
|
|
|
$scope.destroy_link = function(data) {
|
|
var i = 0;
|
|
var link = null;
|
|
var index = -1;
|
|
for (i = 0; i < $scope.links.length; i++) {
|
|
link = $scope.links[i];
|
|
if (link.id === data.id &&
|
|
link.from_device.id === data.from_device_id &&
|
|
link.to_device.id === data.to_device_id &&
|
|
link.to_interface.id === data.to_interface_id &&
|
|
link.from_interface.id === data.from_interface_id) {
|
|
link.from_interface.link = null;
|
|
link.to_interface.link = null;
|
|
index = $scope.links.indexOf(link);
|
|
$scope.links.splice(index, 1);
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.onDeviceMove = function(data) {
|
|
$scope.move_device(data);
|
|
};
|
|
|
|
$scope.move_device = function(data) {
|
|
var i = 0;
|
|
var j = 0;
|
|
for (i = 0; i < $scope.devices.length; i++) {
|
|
if ($scope.devices[i].id === data.id) {
|
|
$scope.devices[i].x = data.x;
|
|
$scope.devices[i].y = data.y;
|
|
for (j = 0; j < $scope.devices[i].interfaces.length; j ++) {
|
|
$scope.devices[i].interfaces[j].dot();
|
|
if ($scope.devices[i].interfaces[j].link !== null) {
|
|
$scope.devices[i].interfaces[j].link.to_interface.dot();
|
|
$scope.devices[i].interfaces[j].link.from_interface.dot();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.onClientId = function(data) {
|
|
$scope.client_id = data;
|
|
};
|
|
|
|
$scope.onTopology = function(data) {
|
|
$scope.topology_id = data.topology_id;
|
|
$scope.panX = data.panX;
|
|
$scope.panY = data.panX;
|
|
$scope.current_scale = data.scale;
|
|
$scope.$emit('awxNet-UpdateZoomWidget', $scope.current_scale, true);
|
|
$scope.link_id_seq = util.natural_numbers(data.link_id_seq);
|
|
$scope.device_id_seq = util.natural_numbers(data.device_id_seq);
|
|
};
|
|
|
|
$scope.onDeviceSelected = function(data) {
|
|
var i = 0;
|
|
for (i = 0; i < $scope.devices.length; i++) {
|
|
if ($scope.devices[i].id === data.id) {
|
|
$scope.devices[i].remote_selected = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.onDeviceUnSelected = function(data) {
|
|
var i = 0;
|
|
for (i = 0; i < $scope.devices.length; i++) {
|
|
if ($scope.devices[i].id === data.id) {
|
|
$scope.devices[i].remote_selected = false;
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.onSnapshot = function (data) {
|
|
|
|
//Erase the existing state
|
|
$scope.devices = [];
|
|
$scope.links = [];
|
|
$scope.devices_by_name = {};
|
|
|
|
var device_map = {};
|
|
var device_interface_map = {};
|
|
var i = 0;
|
|
var j = 0;
|
|
var device = null;
|
|
var intf = null;
|
|
var new_device = null;
|
|
var new_intf = null;
|
|
var max_device_id = null;
|
|
var max_link_id = null;
|
|
var min_x = null;
|
|
var min_y = null;
|
|
var max_x = null;
|
|
var max_y = null;
|
|
var new_link = null;
|
|
|
|
//Build the devices
|
|
for (i = 0; i < data.devices.length; i++) {
|
|
device = data.devices[i];
|
|
if (max_device_id === null || device.id > max_device_id) {
|
|
max_device_id = device.id;
|
|
}
|
|
if (min_x === null || device.x < min_x) {
|
|
min_x = device.x;
|
|
}
|
|
if (min_y === null || device.y < min_y) {
|
|
min_y = device.y;
|
|
}
|
|
if (max_x === null || device.x > max_x) {
|
|
max_x = device.x;
|
|
}
|
|
if (max_y === null || device.y > max_y) {
|
|
max_y = device.y;
|
|
}
|
|
if (device.device_type === undefined) {
|
|
device.device_type = device.type;
|
|
}
|
|
new_device = new models.Device(device.id,
|
|
device.name,
|
|
device.x,
|
|
device.y,
|
|
device.device_type,
|
|
device.host_id);
|
|
if (device.variables !== undefined) {
|
|
new_device.variables = device.variables;
|
|
}
|
|
|
|
for (j=0; j < $scope.inventory_toolbox.items.length; j++) {
|
|
if($scope.inventory_toolbox.items[j].name === device.name) {
|
|
$scope.inventory_toolbox.items.splice(j, 1);
|
|
break;
|
|
}
|
|
}
|
|
new_device.interface_seq = util.natural_numbers(device.interface_id_seq);
|
|
new_device.process_id_seq = util.natural_numbers(device.process_id_seq);
|
|
$scope.devices.push(new_device);
|
|
$scope.devices_by_name[new_device.name] = new_device;
|
|
device_map[device.id] = new_device;
|
|
device_interface_map[device.id] = {};
|
|
for (j = 0; j < device.interfaces.length; j++) {
|
|
intf = device.interfaces[j];
|
|
new_intf = (new models.Interface(intf.id,
|
|
intf.name));
|
|
new_intf.device = new_device;
|
|
device_interface_map[device.id][intf.id] = new_intf;
|
|
new_device.interfaces.push(new_intf);
|
|
new_device.interfaces_by_name[new_intf.name] = new_intf;
|
|
}
|
|
}
|
|
|
|
//Build the links
|
|
var link = null;
|
|
for (i = 0; i < data.links.length; i++) {
|
|
link = data.links[i];
|
|
if (max_link_id === null || link.id > max_link_id) {
|
|
max_link_id = link.id;
|
|
}
|
|
new_link = new models.Link(link.id,
|
|
device_map[link.from_device_id],
|
|
device_map[link.to_device_id],
|
|
device_interface_map[link.from_device_id][link.from_interface_id],
|
|
device_interface_map[link.to_device_id][link.to_interface_id]);
|
|
new_link.name = link.name;
|
|
$scope.links.push(new_link);
|
|
device_interface_map[link.from_device_id][link.from_interface_id].link = new_link;
|
|
device_interface_map[link.to_device_id][link.to_interface_id].link = new_link;
|
|
}
|
|
|
|
var diff_x;
|
|
var diff_y;
|
|
|
|
// Calculate the new scale to show the entire diagram
|
|
if (min_x !== null && min_y !== null && max_x !== null && max_y !== null) {
|
|
diff_x = max_x - min_x;
|
|
diff_y = max_y - min_y;
|
|
|
|
$scope.current_scale = Math.min(2, Math.max(0.10, Math.min((window.innerWidth-200)/diff_x, (window.innerHeight-300)/diff_y)));
|
|
$scope.$emit('awxNet-UpdateZoomWidget', $scope.current_scale, true);
|
|
$scope.updateScaledXY();
|
|
$scope.updatePanAndScale();
|
|
}
|
|
// Calculate the new panX and panY to show the entire diagram
|
|
if (min_x !== null && min_y !== null) {
|
|
diff_x = max_x - min_x;
|
|
diff_y = max_y - min_y;
|
|
$scope.panX = $scope.current_scale * (-min_x - diff_x/2) + window.innerWidth/2;
|
|
$scope.panY = $scope.current_scale * (-min_y - diff_y/2) + window.innerHeight/2;
|
|
$scope.updateScaledXY();
|
|
$scope.updatePanAndScale();
|
|
}
|
|
|
|
//Update the device_id_seq to be greater than all device ids to prevent duplicate ids.
|
|
if (max_device_id !== null) {
|
|
$scope.device_id_seq = util.natural_numbers(max_device_id);
|
|
}
|
|
//
|
|
//Update the link_id_seq to be greater than all link ids to prevent duplicate ids.
|
|
if (max_link_id !== null) {
|
|
$scope.link_id_seq = util.natural_numbers(max_link_id);
|
|
}
|
|
|
|
console.log(['data.inventory_toolbox', data.inventory_toolbox]);
|
|
if (data.inventory_toolbox !== undefined) {
|
|
$scope.inventory_toolbox.items = [];
|
|
for (i = 0; i < data.inventory_toolbox.length; i++) {
|
|
device = data.inventory_toolbox[i];
|
|
console.log(device);
|
|
if (device.device_type === undefined) {
|
|
device.device_type = device.type;
|
|
}
|
|
new_device = new models.Device(device.id,
|
|
device.name,
|
|
device.x,
|
|
device.y,
|
|
device.device_type,
|
|
device.host_id);
|
|
if (device.variables !== undefined) {
|
|
new_device.variables = device.variables;
|
|
}
|
|
$scope.inventory_toolbox.items.push(new_device);
|
|
}
|
|
console.log($scope.inventory_toolbox.items);
|
|
}
|
|
|
|
$scope.updateInterfaceDots();
|
|
$scope.$emit('awxNet-instatiateSelect', $scope.devices);
|
|
};
|
|
|
|
$scope.updateInterfaceDots = function() {
|
|
var i = 0;
|
|
var j = 0;
|
|
var devices = $scope.devices;
|
|
for (i = devices.length - 1; i >= 0; i--) {
|
|
for (j = devices[i].interfaces.length - 1; j >= 0; j--) {
|
|
devices[i].interfaces[j].dot();
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.control_socket.onmessage = function(message) {
|
|
$scope.first_channel.send('Message', message);
|
|
$scope.$apply();
|
|
};
|
|
|
|
$scope.control_socket.onopen = function() {
|
|
//ignore
|
|
};
|
|
|
|
$scope.test_socket.onmessage = function(message) {
|
|
$scope.test_channel.send('Message', message);
|
|
$scope.$apply();
|
|
};
|
|
|
|
$scope.test_socket.onopen = function() {
|
|
//ignore
|
|
};
|
|
|
|
// Call onopen directly if $scope.control_socket is already open
|
|
if ($scope.control_socket.readyState === WebSocket.OPEN) {
|
|
$scope.control_socket.onopen();
|
|
}
|
|
// Call onopen directly if $scope.test_socket is already open
|
|
if ($scope.test_socket.readyState === WebSocket.OPEN) {
|
|
$scope.test_socket.onopen();
|
|
}
|
|
|
|
$scope.send_test_message = function (message) {
|
|
var i = 0;
|
|
message.sender = $scope.test_client_id;
|
|
message.message_id = $scope.message_id_seq();
|
|
if (message.constructor.name === "MultipleMessage") {
|
|
for (i=0; i < message.messages.length; i++) {
|
|
message.messages[i].message_id = $scope.message_id_seq();
|
|
}
|
|
}
|
|
var data = messages.serialize(message);
|
|
if (!$scope.disconnected) {
|
|
$scope.test_socket.send(data);
|
|
}
|
|
};
|
|
|
|
$scope.send_control_message = function (message) {
|
|
var i = 0;
|
|
message.sender = $scope.client_id;
|
|
message.message_id = $scope.message_id_seq();
|
|
if (message.constructor.name === "MultipleMessage") {
|
|
for (i=0; i < message.messages.length; i++) {
|
|
message.messages[i].message_id = $scope.message_id_seq();
|
|
}
|
|
}
|
|
var data = messages.serialize(message);
|
|
if (!$scope.disconnected) {
|
|
$scope.control_socket.send(data);
|
|
}
|
|
};
|
|
|
|
|
|
// End web socket
|
|
//
|
|
|
|
angular.element($window).bind('resize', function(){
|
|
|
|
$scope.graph.width = $window.innerWidth;
|
|
$scope.graph.right_column = 300;
|
|
$scope.graph.height = $window.innerHeight;
|
|
|
|
$scope.update_size();
|
|
|
|
// manuall $digest required as resize event
|
|
// is outside of angular
|
|
$scope.$digest();
|
|
});
|
|
|
|
//60fps ~ 17ms delay
|
|
setInterval( function () {
|
|
$scope.frame = Math.floor(window.performance.now());
|
|
$scope.$apply();
|
|
}, 17);
|
|
|
|
console.log("Network UI started");
|
|
|
|
$scope.$on('$destroy', function () {
|
|
console.log("Network UI stopping");
|
|
$scope.first_channel.send('UnbindDocument', {});
|
|
});
|
|
|
|
$scope.update_toolbox_heights = function(){
|
|
var toolboxTopMargin = $('.Networking-top').height();
|
|
var toolboxTitleMargin = toolboxTopMargin + 35;
|
|
var toolboxHeight = $scope.graph.height - toolboxTopMargin;
|
|
|
|
let toolboxes = ['inventory_toolbox'];
|
|
toolboxes.forEach((toolbox) => {
|
|
$scope[toolbox].y = toolboxTopMargin;
|
|
$scope[toolbox].height = toolboxHeight;
|
|
$scope[toolbox].title_coordinates.y = toolboxTitleMargin;
|
|
});
|
|
|
|
$('.Networking-detailPanel').height(toolboxHeight);
|
|
$('.Networking-detailPanel').css('top', toolboxTopMargin);
|
|
};
|
|
|
|
$scope.update_size = function () {
|
|
$scope.update_toolbox_heights();
|
|
};
|
|
|
|
setInterval( function () {
|
|
var test_event = null;
|
|
if ($scope.test_events.length > 0) {
|
|
test_event = $scope.test_events.shift();
|
|
test_event.sender = 0;
|
|
try {
|
|
$scope.first_channel.send(test_event.msg_type, test_event);
|
|
} catch (err) {
|
|
console.log(["Test Error:", $scope.current_test, err]);
|
|
$scope.test_errors.push(err);
|
|
}
|
|
}
|
|
$scope.$apply();
|
|
}, 10);
|
|
|
|
ConfigService
|
|
.getConfig()
|
|
.then(function(config){
|
|
$scope.version = config.version;
|
|
});
|
|
|
|
$scope.reset_coverage = function() {
|
|
var i = null;
|
|
var coverage = null;
|
|
var f = null;
|
|
if (typeof(window.__coverage__) !== "undefined" && window.__coverage__ !== null) {
|
|
for (f in window.__coverage__) {
|
|
coverage = window.__coverage__[f];
|
|
for (i in coverage.b) {
|
|
coverage.b[i] = [0, 0];
|
|
}
|
|
for (i in coverage.f) {
|
|
coverage.f[i] = 0;
|
|
}
|
|
for (i in coverage.s) {
|
|
coverage.s[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.reset_flags = function () {
|
|
$scope.debug = {'hidden': true};
|
|
$scope.hide_buttons = false;
|
|
$scope.hide_links = false;
|
|
$scope.hide_interfaces = false;
|
|
};
|
|
|
|
|
|
$scope.reset_fsm_state = function () {
|
|
$scope.hotkeys_controller.state = hotkeys.Start;
|
|
$scope.hotkeys_controller.state.start($scope.hotkeys_controller);
|
|
$scope.keybindings_controller.state = keybindings.Start;
|
|
$scope.keybindings_controller.state.start($scope.keybindings_controller);
|
|
$scope.view_controller.state = view.Start;
|
|
$scope.view_controller.state.start($scope.view_controller);
|
|
$scope.move_controller.state = move.Start;
|
|
$scope.move_controller.state.start($scope.move_controller);
|
|
$scope.move_readonly_controller.state = move_readonly.Start;
|
|
$scope.move_readonly_controller.state.start($scope.move_readonly_controller);
|
|
$scope.details_panel_controller.state = details_panel_fsm.Start;
|
|
$scope.details_panel_controller.state.start($scope.details_panel_controller);
|
|
$scope.time_controller.state = time.Start;
|
|
$scope.time_controller.state.start($scope.time_controller);
|
|
$scope.inventory_toolbox_controller.state = toolbox_fsm.Start;
|
|
$scope.inventory_toolbox_controller.state.start($scope.inventory_toolbox_controller);
|
|
$scope.mode_controller.state = mode_fsm.Start;
|
|
$scope.mode_controller.state.start($scope.mode_controller);
|
|
};
|
|
|
|
$scope.reset_toolboxes = function () {
|
|
$scope.inventory_toolbox.items = [];
|
|
$scope.inventory_toolbox.scroll_offset = 0;
|
|
};
|
|
|
|
$scope.cancel_animations = function () {
|
|
|
|
var i = 0;
|
|
for (i = 0; i < $scope.animations.length; i++) {
|
|
this.animations[i].fsm.handle_message('AnimationCancelled');
|
|
}
|
|
$scope.animations = [];
|
|
};
|
|
};
|
|
|
|
exports.NetworkUIController = NetworkUIController;
|
|
console.log("Network UI loaded");
|