Adds host detail panel UI and improves toolbox UI

* Changes Layers' panel's default setting to not expanded
* Adds OffScreen2 state to handle the case where a toolbox is both offscreen and disabled
* Adds a collapsed view of the toolbox, as well as a model for ActionIcons
    which is a model whose purpose is to connect the button FSM with the
    chevron icons that are used on the toolbox.
* Adds action-icon directive
* Enables/disables the icons if they're not shown
* Fixes initial state of the toolboxes
* Creates context menu and context menu buttons in the network UI
* Adds extra vars to details panel on left hand side
This commit is contained in:
Jared Tabor 2017-11-21 11:51:43 -08:00 committed by Ben Thomasson
parent 519983308a
commit a1f639bc8f
No known key found for this signature in database
GPG Key ID: 5818EF4CC895D5F5
26 changed files with 703 additions and 73 deletions

View File

@ -1,11 +1,19 @@
finite_state_machine_id: 14
finite_state_machine_id: 24
name: toolbox
states:
- id: 2
- id: 9
label: Disabled
x: 885
y: 141
- id: 7
label: OffScreen
x: 1140
y: 217
- id: 1
label: Selected
x: 1180
y: 959
- id: 6
- id: 2
label: Move
x: 1409
y: 741
@ -18,18 +26,34 @@ states:
x: 567
y: 431
- id: 5
label: Start
x: 892
y: 216
- id: 7
label: Selecting
x: 888
y: 710
- id: 1
- id: 6
label: Dropping
x: 1358
y: 431
- id: 8
label: Start
x: 672
y: 196
- id: 10
label: OffScreen2
x: 1115
y: -12
transitions:
- from_state: Ready
label: onDisable
to_state: Disabled
- from_state: OffScreen2
label: onToggleToolbox
to_state: Disabled
- from_state: OffScreen2
label: onEnable
to_state: OffScreen
- from_state: Ready
label: onToggleToolbox
to_state: OffScreen
- from_state: Selecting
label: onMouseDown
to_state: Selected
@ -51,6 +75,12 @@ transitions:
- from_state: Scrolling
label: onMouseWheel
to_state: Ready
- from_state: OffScreen
label: onToggleToolbox
to_state: Ready
- from_state: Disabled
label: onEnable
to_state: Ready
- from_state: Ready
label: onMouseWheel
to_state: Scrolling
@ -60,3 +90,9 @@ transitions:
- from_state: Move
label: onMouseUp
to_state: Dropping
- from_state: OffScreen
label: onDisable
to_state: OffScreen2
- from_state: Disabled
label: onToggleToolbox
to_state: OffScreen2

View File

@ -33,9 +33,16 @@ function _Pressed () {
inherits(_Pressed, _State);
var Pressed = new _Pressed();
exports.Pressed = Pressed;
function _Disabled () {
this.name = 'Disabled';
}
inherits(_Disabled, _State);
var Disabled = new _Disabled();
exports.Disabled = Disabled;
// Begin ready state
_Ready.prototype.onMouseDown = function (controller) {
controller.changeState(Pressed);
@ -45,6 +52,20 @@ _Ready.prototype.onMouseDown.transitions = ['Pressed'];
_Ready.prototype.onTouchStart = _Ready.prototype.onMouseDown;
_Ready.prototype.start = function (controller) {
controller.scope.enabled = true;
};
_Ready.prototype.onDisable = function (controller) {
controller.changeState(Disabled);
};
_Ready.prototype.onDisable.transitions = ['Disabled'];
// end ready state
_Start.prototype.start = function (controller) {
@ -57,8 +78,8 @@ _Start.prototype.start.transitions = ['Ready'];
_Clicked.prototype.start = function (controller) {
controller.scope.is_pressed = false;
controller.scope.callback(controller.scope);
controller.changeState(Ready);
controller.scope.callback(controller.scope);
};
_Clicked.prototype.start.transitions = ['Ready'];
@ -75,3 +96,16 @@ _Pressed.prototype.onMouseUp = function (controller) {
_Pressed.prototype.onMouseUp.transitions = ['Clicked'];
_Pressed.prototype.onTouchEnd = _Pressed.prototype.onMouseUp;
_Disabled.prototype.onEnable = function (controller) {
controller.changeState(Ready);
};
_Disabled.prototype.onEnable.transitions = ['Ready'];
_Disabled.prototype.start = function (controller) {
controller.scope.enabled = false;
};

View File

@ -98,4 +98,3 @@ _ButtonPressed.prototype.onMouseUp = function (controller, msg_type, $event) {
_ButtonPressed.prototype.onMouseUp.transitions = ['Ready'];
_ButtonPressed.prototype.onTouchEnd = _ButtonPressed.prototype.onMouseUp;

View File

@ -0,0 +1,12 @@
/* Copyright (c) 2017 Red Hat, Inc. */
function chevronLeft () {
return {
restrict: 'A',
templateUrl: '/static/network_ui/widgets/chevron_left.svg',
scope: {
actionIcon: '='
}
};
}
exports.chevronLeft = chevronLeft;

View File

@ -0,0 +1,12 @@
/* Copyright (c) 2017 Red Hat, Inc. */
function chevronRight () {
return {
restrict: 'A',
templateUrl: '/static/network_ui/widgets/chevron_right.svg',
scope: {
actionIcon: '='
}
};
}
exports.chevronRight = chevronRight;

View File

@ -0,0 +1,13 @@
/* Copyright (c) 2017 Red Hat, Inc. */
function contextMenuButton () {
return {
restrict: 'A',
templateUrl: '/static/network_ui/widgets/context_menu_button.svg',
scope: {
contextMenuButton: '=',
contextMenu: '='
}
};
}
exports.contextMenuButton = contextMenuButton;

View File

@ -0,0 +1,12 @@
/* Copyright (c) 2017 Red Hat, Inc. */
function contextMenu () {
return {
restrict: 'A',
templateUrl: '/static/network_ui/widgets/context_menu.svg',
scope: {
contextMenu: '='
}
};
}
exports.contextMenu = contextMenu;

View File

@ -1,9 +1,11 @@
/* Copyright (c) 2017 Red Hat, Inc. */
function FSMController (scope, initial_state, next_controller) {
function FSMController (scope, initial_state, next_controller, name) {
this.scope = scope;
this.state = initial_state;
this.state.start(this);
this.next_controller = next_controller;
this.name = name;
this.debug = false;
this.state.start(this);
}
exports.FSMController = FSMController;

View File

@ -68,8 +68,12 @@ _State.prototype.start = function (controller) {
_Start.prototype.start = function (controller) {
controller.changeState(Rack);
controller.scope.app_toolbox_controller.handle_message('Disable', {});
controller.scope.inventory_toolbox_controller.handle_message('Disable', {});
controller.scope.rack_toolbox_controller.handle_message('Disable', {});
controller.scope.site_toolbox_controller.handle_message('Disable', {});
controller.changeState(Rack);
};
_Start.prototype.start.transitions = ['MultiSite'];
@ -86,13 +90,13 @@ _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_toolbox_controller.handle_message('Enable', {});
controller.scope.rack_controller.changeState(rack_fsm.Ready);
};
_Site.prototype.end = function (controller) {
controller.scope.rack_toolbox.enabled = false;
controller.scope.rack_toolbox_controller.handle_message('Disable', {});
controller.scope.rack_controller.changeState(rack_fsm.Disable);
};
@ -124,13 +128,13 @@ _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_toolbox_controller.handle_message('Enable', {});
controller.scope.site_controller.changeState(site_fsm.Ready);
};
_MultiSite.prototype.end = function (controller) {
controller.scope.site_toolbox.enabled = false;
controller.scope.site_toolbox_controller.handle_message('Disable', {});
controller.scope.site_controller.changeState(site_fsm.Disable);
};
@ -147,12 +151,12 @@ _MultiSite.prototype.onMouseWheel.transitions = ['Site'];
_Device.prototype.start = function (controller) {
controller.scope.current_mode = controller.state.name;
controller.scope.app_toolbox.enabled = true;
controller.scope.app_toolbox_controller.handle_message('Enable', {});
};
_Device.prototype.end = function (controller) {
controller.scope.app_toolbox.enabled = false;
controller.scope.app_toolbox_controller.handle_message('Disable', {});
};
_Device.prototype.onMouseWheel = function (controller, msg_type, $event) {
@ -174,14 +178,14 @@ _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.inventory_toolbox_controller.handle_message('Enable', {});
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.inventory_toolbox_controller.handle_message('Disable', {});
controller.scope.move_controller.changeState(move.Disable);
controller.scope.group_controller.changeState(group.Disable);
};
@ -199,4 +203,3 @@ _Rack.prototype.onMouseWheel = function (controller, msg_type, $event) {
controller.next_controller.handle_message(msg_type, $event);
};
_Rack.prototype.onMouseWheel.transitions = ['Site', 'Device'];

View File

@ -289,6 +289,27 @@ Link.prototype.plength = function (x, y) {
return util.pDistance(x, y, x1, y1, x2, y2);
};
function ActionIcon(name, x, y, r, callback, enabled) {
this.name = name;
this.x = x;
this.y = y;
this.r = r;
this.callback = callback;
this.is_pressed = false;
this.mouse_over = false;
this.enabled = enabled;
this.fsm = new fsm.FSMController(this, enabled ? button.Start : button.Disabled, null, name+'button_fsm');
}
exports.ActionIcon = ActionIcon;
ActionIcon.prototype.is_selected = function (x, y) {
return (x > this.x - this.r &&
x < this.x + this.r &&
y > this.y - this.r &&
y < this.y + this.r);
};
function Button(name, x, y, width, height, callback) {
this.name = name;
@ -299,7 +320,8 @@ function Button(name, x, y, width, height, callback) {
this.callback = callback;
this.is_pressed = false;
this.mouse_over = false;
this.fsm = new fsm.FSMController(this, button.Start, null);
this.enabled = true;
this.fsm = new fsm.FSMController(this, button.Start, null, name+'button_fsm');
}
exports.Button = Button;
@ -326,7 +348,8 @@ function ToggleButton(name, x, y, width, height, toggle_callback, untoggle_callb
this.toggle_callback = toggle_callback;
this.untoggle_callback = untoggle_callback;
this.mouse_over = false;
this.fsm = new fsm.FSMController(this, button.Start, null);
this.enabled = true;
this.fsm = new fsm.FSMController(this, button.Start, null, name+'toggle_button_fsm');
}
inherits(ToggleButton, Button);
exports.ToggleButton = ToggleButton;
@ -342,6 +365,54 @@ ToggleButton.prototype.toggle = function () {
}
};
function ContextMenu(name, x, y, width, height, callback, enabled, buttons) {
this.name = name;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.callback = callback;
this.is_pressed = false;
this.mouse_over = false;
this.enabled = enabled;
this.buttons = buttons;
this.fsm = new fsm.FSMController(this, button.Start, null, name+'button_fsm');
}
exports.ContextMenu = ContextMenu;
ContextMenu.prototype.is_selected = function (x, y) {
return (x > this.x &&
x < this.x + this.width &&
y > this.y &&
y < this.y + this.height);
};
function ContextMenuButton(name, x, y, width, height, callback) {
this.name = name;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.callback = callback;
this.is_pressed = false;
this.mouse_over = false;
this.enabled = true;
this.fsm = new fsm.FSMController(this, button.Start, null, name+'button_fsm');
}
exports.ContextMenuButton = ContextMenuButton;
ContextMenuButton.prototype.is_selected = function (x, y) {
return (x > this.x &&
x < this.x + this.width &&
y > this.y &&
y < this.y + this.height);
};
function Task(id, name) {
this.id = id;

View File

@ -15,6 +15,10 @@ 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 chevronRight = require('./chevron.right.directive.js');
var chevronLeft = require('./chevron.left.directive.js');
var contextMenu = require('./context.menu.directive.js');
var contextMenuButton = require('./context.menu.button.directive.js');
var process = require('./process.directive.js');
var configuration = require('./configuration.directive.js');
var map = require('./map.directive.js');
@ -49,6 +53,10 @@ var networkUI = angular.module('networkUI', [
.directive('awxNetSite', site.site)
.directive('awxNetSiteIcon', siteIcon.siteIcon)
.directive('awxNetRackIcon', rackIcon.rackIcon)
.directive('awxNetChevronRightIcon', chevronRight.chevronRight)
.directive('awxNetChevronLeftIcon', chevronLeft.chevronLeft)
.directive('awxNetContextMenu', contextMenu.contextMenu)
.directive('awxNetContextMenuButton', contextMenuButton.contextMenuButton)
.directive('awxNetProcess', process.process)
.directive('awxNetConfiguration', configuration.configuration)
.directive('awxNetMap', map.map)

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2017 Red Hat, Inc. */
var _ = require('lodash');
// var _ = require('lodash');
var angular = require('angular');
var fsm = require('./fsm.js');
var null_fsm = require('./null.fsm.js');
@ -30,7 +30,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.http = $http;
$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
@ -82,7 +82,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.last_event = null;
$scope.cursor = {'x':100, 'y': 100, 'hidden': false};
$scope.debug = {'hidden': false};
$scope.debug = {'hidden': true};
$scope.hide_buttons = false;
$scope.hide_links = false;
$scope.hide_interfaces = false;
@ -95,6 +95,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$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.overall_toolbox_collapsed = false;
$scope.time_pointer = -1;
$scope.frame = 0;
$scope.recording = false;
@ -112,27 +113,29 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
'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);
$scope.null_controller = new fsm.FSMController($scope, null_fsm.Start, null, 'null_fsm');
$scope.hotkeys_controller = new fsm.FSMController($scope, hotkeys.Start, $scope.null_controller, 'hotkeys_fsm');
$scope.view_controller = new fsm.FSMController($scope, view.Start, $scope.hotkeys_controller, 'null_fsm');
$scope.device_detail_controller = new fsm.FSMController($scope, device_detail_fsm.Start, $scope.view_controller, 'device_detail_fsm');
$scope.move_controller = new fsm.FSMController($scope, move.Start, $scope.device_detail_controller, 'move_fsm');
$scope.link_controller = new fsm.FSMController($scope, link.Start, $scope.move_controller, 'link_fsm');
$scope.stream_controller = new fsm.FSMController($scope, stream_fsm.Start, $scope.link_controller, 'stream_fsm');
$scope.group_controller = new fsm.FSMController($scope, group.Start, $scope.stream_controller, 'group_fsm');
$scope.rack_controller = new fsm.FSMController($scope, rack_fsm.Disable, $scope.group_controller, 'rack_fsm');
$scope.site_controller = new fsm.FSMController($scope, site_fsm.Disable, $scope.rack_controller, 'site_fsm');
$scope.time_controller = new fsm.FSMController($scope, time.Start, $scope.site_controller, 'time_fsm');
$scope.app_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Disabled, $scope.time_controller, 'toolbox_fsm');
//App Toolbox Setup
$scope.app_toolbox = new models.ToolBox(0, 'Process', 'app', 10, 200, 150, $scope.graph.height - 200 - 100);
$scope.app_toolbox = new models.ToolBox(0, 'Process', 'app', 0, 40, 200, $scope.graph.height - 40);
$scope.app_toolbox.title_coordinates = {x: 70, y: 70};
$scope.app_toolbox.spacing = 150;
$scope.app_toolbox.enabled = false;
$scope.app_toolbox_controller.toolbox = $scope.app_toolbox;
$scope.app_toolbox_controller.debug = true;
$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.Process(0, 'BGP', 'process', 0, 0));
$scope.app_toolbox.items.push(new models.Process(0, 'OSPF', 'process', 0, 0));
$scope.app_toolbox.items.push(new models.Process(0, 'STP', 'process', 0, 0));
@ -142,19 +145,19 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.app_toolbox.items[i].icon = true;
}
$scope.inventory_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.app_toolbox_controller);
$scope.inventory_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.app_toolbox_controller, 'inventory_toolbox_fsm');
//Inventory Toolbox Setup
$scope.inventory_toolbox = new models.ToolBox(0, 'Inventory', 'device', 10, 200, 150, $scope.graph.height - 200 - 100);
$scope.inventory_toolbox = new models.ToolBox(0, 'Inventory', 'device', 0, 40, 200, $scope.graph.height - 40);
if (!$scope.disconnected) {
console.log($location.protocol() + "://" + $location.host() + ':' + $location.port());
console.log($scope.my_location);
function add_host (host) {
var add_host = function(host) {
console.log(host);
var device = new models.Device(0, host.data.name, 0, 0, host.data.type);
device.icon = true;
$scope.inventory_toolbox.items.push(device);
}
};
$http.get('/api/v2/inventories/' + $scope.inventory_id + '/hosts/?format=json')
.then(function(inventory) {
console.log(inventory);
@ -178,26 +181,29 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
for (i=0; i < results.length; i++) {
add_host(results[i]);
}
console.log(['done', x]);
});
});
}
$scope.inventory_toolbox.spacing = 150;
$scope.inventory_toolbox.enabled = true;
$scope.inventory_toolbox.title_coordinates = {x: 60, y: 70};
$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_controller.handle_message("PasteDevice", new messages.PasteDevice(selected_item));
};
//End Inventory Toolbox Setup
$scope.rack_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.inventory_toolbox_controller);
$scope.rack_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.inventory_toolbox_controller, 'rack_toolbox_fsm');
//Rack Toolbox Setup
$scope.rack_toolbox = new models.ToolBox(0, 'Rack', 'rack', 10, 200, 150, $scope.graph.height - 200 - 100);
$scope.rack_toolbox = new models.ToolBox(0, 'Rack', 'rack', 0, 40, 200, $scope.graph.height - 40);
$scope.rack_toolbox.title_coordinates = {x: 80, y: 70};
$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.debug = true;
$scope.rack_toolbox_controller.dropped_action = function (selected_item) {
$scope.first_controller.handle_message("PasteRack", new messages.PasteRack(selected_item));
};
@ -206,13 +212,15 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$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);
$scope.site_toolbox_controller = new fsm.FSMController($scope, toolbox_fsm.Start, $scope.rack_toolbox_controller, 'site_toolbox_fsm');
//Site Toolbox Setup
$scope.site_toolbox = new models.ToolBox(0, 'Sites', 'sites', 10, 200, 150, $scope.graph.height - 200 - 100);
$scope.site_toolbox = new models.ToolBox(0, 'Sites', 'sites', 0, 40, 200, $scope.graph.height - 40);
$scope.site_toolbox.title_coordinates = {x: 80, y: 70};
$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.debug = true;
$scope.site_toolbox_controller.dropped_action = function (selected_item) {
$scope.first_controller.handle_message("PasteSite", new messages.PasteSite(selected_item));
};
@ -221,8 +229,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$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.buttons_controller = new fsm.FSMController($scope, buttons.Start, $scope.site_toolbox_controller, 'buttons_fsm');
$scope.mode_controller = new fsm.FSMController($scope, mode_fsm.Start, $scope.buttons_controller, 'mode_fsm');
$scope.first_controller = $scope.mode_controller;
var getMouseEventResult = function (mouseEvent) {
return "(" + mouseEvent.x + ", " + mouseEvent.y + ")";
@ -458,7 +466,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
var delta = $event.delta;
var deltaX = $event.deltaX;
var deltaY = $event.deltaY;
console.log([$event, delta, deltaX, deltaY]);
// console.log([$event, delta, deltaX, deltaY]);
if ($scope.recording) {
$scope.send_control_message(new messages.MouseWheelEvent($scope.client_id, delta, deltaX, deltaY, $event.type, $event.originalEvent.metaKey));
}
@ -555,8 +563,42 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$event.preventDefault();
};
// Conext Menu
$scope.onDetailsContextButton = function (button) {
console.log(button.name);
if (!$scope.disconnected) {
// this will end up being the id of the host the user clicked on
let host_id = 1;
let url = `/api/v2/hosts/${host_id}/?format=json`;
$http.get(url)
.then(function(host) {
$scope.$emit('retrievedHostData', host.data);
})
.catch(function(httpGets) {
console.log(httpGets);
});
}
};
// Button Event Handlers
//
$scope.onToggleToolboxButtonLeft = function (button) {
console.log(button.name);
$scope.first_controller.handle_message("ToggleToolbox", {});
$scope.action_icons[0].fsm.handle_message("Disable", {});
$scope.action_icons[1].fsm.handle_message("Enable", {});
$scope.overall_toolbox_collapsed = !$scope.overall_toolbox_collapsed;
};
$scope.onToggleToolboxButtonRight = function (button) {
console.log(button.name);
$scope.first_controller.handle_message("ToggleToolbox", {});
$scope.action_icons[0].fsm.handle_message("Enable", {});
$scope.action_icons[1].fsm.handle_message("Disable", {});
$scope.overall_toolbox_collapsed = !$scope.overall_toolbox_collapsed;
};
$scope.onDeployButton = function (button) {
@ -646,22 +688,41 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.group_controller.changeState(group.Ready);
};
$scope.onExportYamlButton = function (button) {
console.log(button);
$window.open('/network_ui/topology.yaml?topology_id=' + $scope.topology_id , '_blank');
};
// Context Menu Buttons
$scope.context_menu_buttons = [
new models.ContextMenuButton("Edit", 210, 200, 160, 26, $scope.onDetailsContextButton),
new models.ContextMenuButton("Details", 236, 231, 160, 26, $scope.onDetailsContextButton)
];
// Context Menus
$scope.context_menus = [
new models.ContextMenu('HOST', 210, 200, 160, 64, $scope.contextMenuCallback, true, $scope.context_menu_buttons)
];
// Icons
$scope.action_icons = [
new models.ActionIcon("chevron-left", 170, $scope.graph.height/2, 16, $scope.onToggleToolboxButtonLeft, true),
new models.ActionIcon("chevron-right", 15, $scope.graph.height/2, 16, $scope.onToggleToolboxButtonRight, false)
];
// Buttons
var button_offset = 200;
$scope.buttons = [
new models.Button("DEPLOY", 10, 48, 70, 30, $scope.onDeployButton),
new models.Button("DESTROY", 90, 48, 80, 30, $scope.onDestroyButton),
new models.Button("RECORD", 180, 48, 80, 30, $scope.onRecordButton),
new models.Button("EXPORT", 270, 48, 70, 30, $scope.onExportButton),
new models.Button("DISCOVER", 350, 48, 80, 30, $scope.onDiscoverButton),
new models.Button("LAYOUT", 440, 48, 70, 30, $scope.onLayoutButton),
new models.Button("CONFIGURE", 520, 48, 90, 30, $scope.onConfigureButton),
new models.Button("EXPORT YAML", 620, 48, 120, 30, $scope.onExportYamlButton),
new models.Button("DEPLOY", button_offset + 10, 48, 70, 30, $scope.onDeployButton),
new models.Button("DESTROY", button_offset + 90, 48, 80, 30, $scope.onDestroyButton),
new models.Button("RECORD", button_offset + 180, 48, 80, 30, $scope.onRecordButton),
new models.Button("EXPORT", button_offset + 270, 48, 70, 30, $scope.onExportButton),
new models.Button("DISCOVER", button_offset + 350, 48, 80, 30, $scope.onDiscoverButton),
new models.Button("LAYOUT", button_offset + 440, 48, 70, 30, $scope.onLayoutButton),
new models.Button("CONFIGURE", button_offset + 520, 48, 90, 30, $scope.onConfigureButton),
new models.Button("EXPORT YAML", button_offset + 620, 48, 120, 30, $scope.onExportYamlButton),
];
var LAYERS_X = 160;
@ -688,6 +749,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.layers = [];
$scope.all_buttons = [];
$scope.all_buttons.extend($scope.context_menu_buttons);
$scope.all_buttons.extend($scope.action_icons);
$scope.all_buttons.extend($scope.buttons);
$scope.all_buttons.extend($scope.layers);

View File

@ -33,9 +33,10 @@
@green: #5CB85C;
@red: #D9534F;
@light-toolbox-background: #f6f6f6;
@icon-background-hover:#337AB7;
.NetworkUI {
background-color: @light-background;
background-color: @light-toolbox-background;
cursor: none;
}
@ -616,13 +617,25 @@
.NetworkUI__toolbox {
stroke: none;
fill: @light-toolbox-background;
fill: @light-background;
}
.NetworkUI__toolbox-collapsed{
fill: @light-background;
stroke: @button-outline;
stroke-width: 1;
rx: 0;
stroke-dasharray: calc(~"100vh - 40px");
stroke-dashoffset: -45;
}
.NetworkUI__toolbox-bezel {
stroke: @group;
stroke-width: 2;
stroke: @button-outline;
stroke-width: 1;
fill: none;
rx: 0;
stroke-dasharray: calc(~"100vh - 40px");
stroke-dashoffset: -200;
}
.NetworkUI__process {
@ -696,3 +709,55 @@
font-size: 8px;
font-family: 'Open Sans';
}
.NetworkUI_chevron{
fill: @button-body-pressed;
}
.NetworkUI_chevron--hover{
cursor: pointer;
fill: white;
}
.NetworkUI_iconBackground{
fill:@button-body;
}
.NetworkUI_iconBackground--hover{
fill:@icon-background-hover;
}
.NetworkUI__toolbox--title{
fill: @dark-widget-detail;
text-transform: uppercase;
font-size: 14px;
font-weight: bold;
}
.NetworkUI__contextMenu{
fill: @light-background;
stroke: @button-outline;
stroke-width: 1;
}
.NetworkUI__contextMenuButton{
fill: @light-background;
}
.NetworkUI__contextMenuButtonText{
fill: @button-text;
font-family: 'Open Sans';
font-size: 14px;
}
.NetworkUI__contextMenuButtonText-hover{
fill: @button-text;
font-family: 'Open Sans';
font-size: 14px;
}
.NetworkUI__contextMenuButton-hover,
.NetworkUI__contextMenuButton-pressed{
fill:@button-body-hover;
}

View File

@ -56,7 +56,26 @@ inherits(_Move, _State);
var Move = new _Move();
exports.Move = Move;
function _OffScreen () {
this.name = 'OffScreen';
}
inherits(_OffScreen, _State);
var OffScreen = new _OffScreen();
exports.OffScreen = OffScreen;
function _OffScreen2 () {
this.name = 'OffScreen2';
}
inherits(_OffScreen2, _State);
var OffScreen2 = new _OffScreen2();
exports.OffScreen2 = OffScreen2;
function _Disabled () {
this.name = 'Disabled';
}
inherits(_Disabled, _State);
var Disabled = new _Disabled();
exports.Disabled = Disabled;
_Dropping.prototype.start = function (controller) {
@ -136,6 +155,10 @@ _Selecting.prototype.onMouseDown = function (controller) {
};
_Selecting.prototype.onMouseDown.transitions = ['Selected', 'Ready'];
_Ready.prototype.onEnable = function () {
};
_Ready.prototype.onMouseDown = function (controller, msg_type, $event) {
if(controller.toolbox.enabled &&
@ -170,7 +193,20 @@ _Ready.prototype.onMouseWheel = function (controller, msg_type, $event) {
};
_Ready.prototype.onMouseWheel.transitions = ['Scrolling'];
_Ready.prototype.onToggleToolbox = function (controller, msg_type, message) {
controller.changeState(OffScreen);
controller.next_controller.handle_message(msg_type, message);
};
_Ready.prototype.onToggleToolbox.transitions = ['OffScreen'];
_Ready.prototype.onDisable = function (controller) {
controller.changeState(Disabled);
};
_Ready.prototype.onDisable.transitions = ['Disabled'];
_Scrolling.prototype.onMouseWheel = function (controller, msg_type, $event) {
@ -215,3 +251,82 @@ _Move.prototype.onMouseMove = function (controller) {
controller.scope.pressedX = controller.scope.mouseX;
controller.scope.pressedY = controller.scope.mouseY;
};
_OffScreen.prototype.onToggleToolbox = function (controller, msg_type, message) {
controller.changeState(Ready);
controller.next_controller.handle_message(msg_type, message);
};
_OffScreen.prototype.onToggleToolbox.transitions = ['Ready'];
_OffScreen.prototype.start = function (controller) {
controller.toolbox.enabled = false;
};
_OffScreen.prototype.end = function (controller) {
controller.toolbox.enabled = true;
};
_OffScreen.prototype.onDisable = function (controller) {
controller.changeState(OffScreen2);
};
_OffScreen.prototype.onDisable.transitions = ['OffScreen2'];
_OffScreen2.prototype.onEnable = function (controller) {
controller.changeState(OffScreen);
};
_OffScreen2.prototype.onEnable.transitions = ['OffScreen'];
_OffScreen2.prototype.onDisable = function () {
};
_OffScreen2.prototype.start = function (controller) {
controller.toolbox.enabled = false;
};
_OffScreen2.prototype.onToggleToolbox = function (controller, msg_type, message) {
controller.changeState(Disabled);
controller.next_controller.handle_message(msg_type, message);
};
_OffScreen2.prototype.onToggleToolbox.transitions = ['Disabled'];
_Disabled.prototype.onDisable = function () {
};
_Disabled.prototype.onEnable = function (controller) {
controller.changeState(Ready);
};
_Disabled.prototype.onEnable.transitions = ['Ready'];
_Disabled.prototype.start = function (controller) {
if(controller.toolbox !== undefined){
controller.toolbox.enabled = false;
}
};
_Disabled.prototype.end = function (controller) {
controller.toolbox.enabled = true;
};
_Disabled.prototype.onToggleToolbox = function (controller, msg_type, message) {
controller.changeState(OffScreen2);
controller.next_controller.handle_message(msg_type, message);
};
_Disabled.prototype.onToggleToolbox.transitions = ['OffScreen2'];

View File

@ -0,0 +1,8 @@
<circle
ng-attr-class="{{actionIcon.is_pressed ? 'NetworkUI__iconBackground--pressed' : actionIcon.mouse_over ? 'NetworkUI_iconBackground--hover' : 'NetworkUI_iconBackground'}}"
class="NetworkUI_iconBackground"
cx=10 cy=9 r=16 />
<path
ng-attr-class="{{actionIcon.is_pressed ? 'NetworkUI_chevron--pressed' : actionIcon.mouse_over ? 'NetworkUI_chevron--hover' : 'NetworkUI_chevron'}}"
ng-attr-transform="scale(0.01)"
d="M1427 301l-531 531 531 531q19 19 19 45t-19 45l-166 166q-19 19-45 19t-45-19l-742-742q-19-19-19-45t19-45l742-742q19-19 45-19t45 19l166 166q19 19 19 45t-19 45z"/>

View File

@ -0,0 +1,7 @@
<circle
ng-attr-class="{{actionIcon.is_pressed ? 'NetworkUI__iconBackground--pressed' : actionIcon.mouse_over ? 'NetworkUI_iconBackground--hover' : 'NetworkUI_iconBackground'}}"
cx=8 cy=9 r=16 />
<path
ng-attr-class="{{actionIcon.is_pressed ? 'NetworkUI_chevron--pressed' : actionIcon.mouse_over ? 'NetworkUI_chevron--hover' : 'NetworkUI_chevron'}}"
ng-attr-transform="scale(0.01)"
d="M1363 877l-742 742q-19 19-45 19t-45-19l-166-166q-19-19-19-45t19-45l531-531-531-531q-19-19-19-45t19-45l166-166q19-19 45-19t45 19l742 742q19 19 19 45t-19 45z"/>

View File

@ -0,0 +1,23 @@
<!-- Copyright (c) 2017 Red Hat, Inc. -->
<filter id="shadowFilter" x="0" y="0" width="102%" height="105%">
<feOffset result="offOut" in="SourceGraphic" dx="20" dy="20" />
<feColorMatrix result = "matrixOut" in = "offOut" type = "matrix" values = "0.2 0 0 0 0 0 0.2 0 0 0 0 0 0.2 0 0 0 0 0 1 0"/>
<feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="10" />
<feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
</filter>
<rect ng-attr-class="{{contextMenu.is_pressed ? 'NetworkUI__contextMenu--button-pressed' : contextMenu.mouse_over ? 'NetworkUI__contextMenu--button-hover' : 'NetworkUI__contextMenu'}}"
x=0
y=0
ng-attr-width={{contextMenu.width}}
ng-attr-height={{contextMenu.height}}
rx=5 ry=5
filter="url(#shadowFilter)">
</rect>
<g>
<g> <!-- context menu buttons -->
<g ng-repeat="button in contextMenu.buttons">
<g awx-net--context-menu-button context-menu-button="button" context-menu="contextMenu"></g>
</g>
</g> <!-- end context menu buttons -->

View File

@ -0,0 +1,13 @@
<!-- Copyright (c) 2017 Red Hat, Inc. -->
<rect ng-attr-class="{{contextMenuButton.is_pressed ? 'NetworkUI__contextMenuButton-pressed' : contextMenuButton.mouse_over ? 'NetworkUI__contextMenuButton-hover' : 'NetworkUI__contextMenuButton'}}"
x= 1
ng-attr-y="{{(contextMenuButton.height * $parent.$index) + 5}}"
ng-attr-width={{contextMenuButton.width-2}}
ng-attr-height={{contextMenuButton.height}}>
</rect>
<text ng-attr-class="{{contextMenuButton.is_pressed ? 'NetworkUI__contextMenuButtonText-pressed' : contextMenuButton.mouse_over ? 'NetworkUI__contextMenuButtonText-hover' : 'NetworkUI__contextMenuButtonText'}}"
x=15
ng-attr-y="{{(contextMenuButton.height * $parent.$index) + 18}}"
dy=".3em"
text-anchor="left">{{contextMenuButton.name}}
</text>

View File

@ -42,5 +42,9 @@
<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>
<text ng-attr-x="{{graph.right_column}}" y="835" class="NetworkUI__debug-text">App Toolbox State: {{app_toolbox_controller.state.name}}</text>
<text ng-attr-x="{{graph.right_column}}" y="855" class="NetworkUI__debug-text">Inventory Toolbox State: {{inventory_toolbox_controller.state.name}}</text>
<text ng-attr-x="{{graph.right_column}}" y="875" class="NetworkUI__debug-text">Rack Toolbox State: {{rack_toolbox_controller.state.name}}</text>
<text ng-attr-x="{{graph.right_column}}" y="895" class="NetworkUI__debug-text">Site Toolbox State: {{site_toolbox_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,5 +1,20 @@
<!-- Copyright (c) 2017 Red Hat, Inc. -->
<!-- begin collapsed toolbox -->
<g ng-if="overall_toolbox_collapsed">
<rect class="NetworkUI__toolbox-collapsed"
x=0
y=40
width=45
ng-attr-height={{toolbox.height}}>
</rect>
<g awx-net-chevron-right-icon
action-icon="action_icons[1]"
ng-if="overall_toolbox_collapsed"
ng-attr-transform="translate({{action_icons[1].x}}, {{action_icons[1].y}})"></g>
</g>
<!-- end collapsed toolbox -->
<g ng-if="toolbox.enabled">
<rect class="NetworkUI__toolbox"
ng-attr-x="{{toolbox.x}}"
@ -7,8 +22,18 @@
ng-attr-width="{{toolbox.width}}"
ng-attr-height="{{toolbox.height}}"
rx=5></rect>
<text
class="NetworkUI__toolbox--title"
ng-attr-transform="translate({{toolbox.title_coordinates.x}},{{toolbox.title_coordinates.y}})">
{{toolbox.name}}
</text>
<g awx-net-chevron-left-icon
action-icon="action_icons[0]"
ng-if="toolbox.enabled"
ng-attr-transform="translate({{action_icons[0].x}}, {{action_icons[0].y}})"></g>
<g clip-path="url(#inventory-toolbox-clip-path)">
<g ng-attr-transform="translate({{toolbox.x}}, {{toolbox.y}})">
<g ng-attr-transform="translate({{toolbox.x}}, {{toolbox.y+20}})">
<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}}"

View File

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

View File

@ -94,6 +94,7 @@
<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}})">
@ -109,6 +110,11 @@
</g>
</g> <!-- end layers -->
</g>
<g awx-net-context-menu
context_menu="context_menus[0]"
ng-if="context_menus[0].enabled"
ng-attr-transform="translate({{context_menus[0].x}}, {{context_menus[0].y}})">
</g>
<g awx-net-debug></g>
<g awx-net-cursor></g>
<g ng-repeat="touch in touches">

View File

@ -58,7 +58,6 @@
.Networking-rightPanel{
border-left: 1px solid @at-color-panel-border;
display:flex;
width:400px;
height: calc(~"100vh - 40px");
padding: 20px;
@ -70,3 +69,34 @@
right: 0px;
background-color: @default-bg;
}
.Networking-panelHeader {
display: flex;
height: 30px;
width:100%;
}
.Networking-panelHeaderText {
color: @default-interface-txt;
flex: 1 0 auto;
font-size: 14px;
font-weight: bold;
margin-right: 10px;
text-transform: uppercase;
}
.Networking-resultRow {
width: 100%;
display: flex;
padding-bottom: 10px;
flex-wrap: wrap;
}
.Networking-resultRow--variables {
flex-direction: column;
#cm-variables-container {
width: 100%;
}
}

View File

@ -7,8 +7,9 @@ function NetworkingController (models, $state, $scope, strings) {
vm.strings = strings;
vm.panelTitle = `${strings.get('state.BREADCRUMB_LABEL')} | ${inventory.name}`;
vm.hostDetail = {};
vm.panelIsExpanded = true;
vm.panelIsExpanded = false;
vm.togglePanel = () => {
vm.panelIsExpanded = !vm.panelIsExpanded;
@ -17,6 +18,13 @@ function NetworkingController (models, $state, $scope, strings) {
vm.close = () => {
$state.go('inventories');
};
$scope.$on('retrievedHostData', (e, hostData) => {
if (!vm.panelIsExpanded) {
vm.panelIsExpanded = true;
}
$scope.hostDetail = hostData;
});
}
NetworkingController.$inject = [

View File

@ -31,6 +31,68 @@
<awx-network-ui></awx-network-ui>
</div>
<div class="Networking-rightPanel" ng-show="vm.panelIsExpanded">
VIEW LAYERS
</div>
<!-- VIEW LAYERS -->
<!--beginning of header-->
<div class="Networking-panelHeader">
<div class="JobResults-panelHeaderText" translate="">DETAILS</div>
<!-- LEFT PANE HEADER ACTIONS -->
<!-- <div> -->
<!-- RELAUNCH ACTION -->
<!-- <button class="List-actionButton" data-placement="top" mode="all" ng-click="relaunchJob()" aw-tool-tip="Relaunch using the same parameters" data-original-title="" title="">
<i class="icon-launch"></i>
</button> -->
<!-- CANCEL ACTION -->
<!-- <button class="List-actionButton List-actionButton--delete ng-hide" data-placement="top" ng-click="cancelJob()" ng-show="job_status == 'running' ||
job_status=='pending' " aw-tool-tip="Cancel" data-original-title="" title="">
<i class="fa fa-minus-circle"></i>
</button> -->
<!-- DELETE ACTION -->
<!-- <button class="List-actionButton
List-actionButton--delete" data-placement="top" ng-click="deleteJob()" ng-hide="job_status == 'running' ||
job_status == 'pending' || !job.summary_fields.user_capabilities.delete" aw-tool-tip="Delete" data-original-title="" title="">
<i class="fa fa-trash-o"></i>
</button>
</div> -->
</div>
<!--end of header-->
<!--beginning of name row -->
<div class="JobResults-resultRow">
<label class="JobResults-resultRowLabel" translate="">Name</label>
<div class="JobResults-resultRowText">
{{hostDetail.name}}
</div>
</div>
<!--end of name row -->
<!-- beginning of extra variable row -->
<div class="JobResults-resultRow
JobResults-resultRow--variables"
ng-show="hostDetail.variables">
<label class="JobResults-resultRowLabel
JobResults-resultRowLabel--fullWidth">
<span translate> Extra Variables </span>
<i class="JobResults-extraVarsHelp fa fa-question-circle"
aw-tool-tip="{{'Read only view of extra variables added to the job template.' | translate}}"
data-placement="top">
</i>
</label>
<textarea
rows="6"
ng-model="hostDetail.variables"
name="variables"
class="form-control Form-textArea Form-textAreaLabel Form-formGroup--fullWidth"
id="pre-formatted-variables"
disabled="disabled">
</textarea>
</div>
<!-- end of extra variable row -->
</div><!--end of Networking-rightPanel -->
</div>

View File

@ -10,7 +10,7 @@ if ($basePath) {
}
import start from './app.start';
// import networkUI from './../network_ui/static/network_ui/src/main.js';
import portalMode from './portal-mode/main';
import systemTracking from './system-tracking/main';
import inventoriesHosts from './inventories-hosts/main';