Adds search field and jump-to a device UI.

Adds a search field in the network UI and a jump-to level menu. This
allows users to quickly find a device on the canvas or jump to a
certain mode/zoom-level.

Adds animation to smooth out the transition from the current viewport
to a viewport centered on the searched for device or zoom-level.

* Adds animation FSM and changes the 0 hot key to use it
* Adds jump to animation
* Adds search bar type ahead
* Adds jump animation to search and jump-to menus
* Adds keybinding FSM
* Updates the dropdown when devices are added/edit/removed
* Highlights the searched for host
This commit is contained in:
Ben Thomasson 2018-02-06 11:43:04 -05:00
parent 00a9283e32
commit 6f3bf4fd1b
No known key found for this signature in database
GPG Key ID: 5818EF4CC895D5F5
27 changed files with 661 additions and 170 deletions

View File

@ -0,0 +1,29 @@
diagram_id: 58
name: animation_fsm
states:
- id: 4
label: Cancelled
x: 590
y: 602
- id: 3
label: Completed
x: 225
y: 604
- id: 2
label: Running
x: 418
y: 362
- id: 1
label: Start
x: 454
y: 158
transitions:
- from_state: Running
label: onAnimationCancelled
to_state: Cancelled
- from_state: Running
label: onAnimationCompleted
to_state: Completed
- from_state: Start
label: start
to_state: Running

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -0,0 +1,25 @@
diagram_id: 60
name: diagram
states:
- id: 3
label: Enabled
x: 842
y: 533
- id: 2
label: Start
x: 839
y: 270
- id: 6
label: Disabled
x: 1231
y: 532
transitions:
- from_state: Start
label: start
to_state: Enabled
- from_state: Disabled
label: onBindDocument
to_state: Enabled
- from_state: Enabled
label: onUnbindDocument
to_state: Disabled

View File

@ -26,7 +26,7 @@ var transition = null;
var i = 0;
while(next_state !== undefined) {
state = implementation[next_state];
transition_iter = Iterator(state.constructor.prototype)
transition_iter = Iterator(state.constructor.prototype);
next_transition = transition_iter.next();
while (next_transition !== undefined) {
transition = state.constructor.prototype[next_transition];

View File

@ -20,19 +20,19 @@ var next_message = message_iter.next();
var next_field = null;
var message = null;
var message_instance = null;
var field = null;
var fields = null;
var i = 0;
// var field = null;
// var i = 0;
while(next_message !== undefined) {
message = implementation[next_message];
try {
message_instance = new message()
message_instance = new message();
} catch(err) {
next_message = message_iter.next();
continue;
}
fields = [];
field_iter = Iterator(message_instance)
field_iter = Iterator(message_instance);
next_field = field_iter.next();
while (next_field !== undefined) {
fields.push(next_field);

View File

@ -1,3 +1,2 @@
@import 'credentials/_index';
@import 'users/tokens/_index';
@import 'networking/_index';

View File

@ -6,7 +6,6 @@ import atFeaturesApplications from '~features/applications';
import atFeaturesCredentials from '~features/credentials';
import atFeaturesTemplates from '~features/templates';
import atFeaturesUsers from '~features/users';
import atFeaturesNetworking from '~features/networking';
const MODULE_NAME = 'at.features';
@ -17,8 +16,7 @@ angular.module(MODULE_NAME, [
atFeaturesApplications,
atFeaturesCredentials,
atFeaturesTemplates,
atFeaturesUsers,
atFeaturesNetworking
atFeaturesUsers
]);
export default MODULE_NAME;

View File

@ -1,66 +0,0 @@
function NetworkingController (models, $state, $scope, strings) {
const vm = this || {};
const {
inventory
} = models;
vm.strings = strings;
vm.panelTitle = `${strings.get('state.BREADCRUMB_LABEL')} | ${inventory.name}`;
vm.hostDetail = {};
vm.rightPanelIsExpanded = false;
vm.leftPanelIsExpanded = true;
vm.jumpToPanelExpanded = false;
vm.keyPanelExpanded = false;
vm.close = () => {
$state.go('inventories');
};
vm.redirectButtonHandler = (string) => {
$scope.$broadcast('toolbarButtonEvent', string);
};
vm.jumpTo = (string) => {
vm.jumpToPanelExpanded = !vm.jumpToPanelExpanded;
vm.keyPanelExpanded = false;
if (string) {
$scope.$broadcast('jumpTo', string);
}
};
vm.key = () => {
vm.keyPanelExpanded = !vm.keyPanelExpanded;
vm.jumpToPanelExpanded = false;
};
$scope.$on('overall_toolbox_collapsed', () => {
vm.leftPanelIsExpanded = !vm.leftPanelIsExpanded;
});
$scope.$on('closeDetailsPanel', () => {
vm.rightPanelIsExpanded = false;
vm.jumpToPanelExpanded = false;
vm.keyPanelExpanded = false;
});
$scope.$on('showDetails', (e, data, expand) => {
if (expand) {
vm.rightPanelIsExpanded = true;
}
if (!_.has(data, 'host_id')) {
$scope.item = data;
} else {
$scope.item = data;
}
});
}
NetworkingController.$inject = [
'resolvedModels',
'$state',
'$scope',
'NetworkingStrings'
];
export default NetworkingController;

View File

@ -0,0 +1,81 @@
/* Copyright (c) 2018 Benjamin Thomasson */
/* Copyright (c) 2018 Red Hat, Inc. */
var inherits = require('inherits');
var fsm = require('./fsm.js');
function _Start () {
this.name = 'Start';
}
inherits(_Start, fsm._State);
var Start = new _Start();
exports.Start = Start;
function _Completed () {
this.name = 'Completed';
}
inherits(_Completed, fsm._State);
var Completed = new _Completed();
exports.Completed = Completed;
function _Cancelled () {
this.name = 'Cancelled';
}
inherits(_Cancelled, fsm._State);
var Cancelled = new _Cancelled();
exports.Cancelled = Cancelled;
function _Running () {
this.name = 'Running';
}
inherits(_Running, fsm._State);
var Running = new _Running();
exports.Running = Running;
_Start.prototype.start = function (controller) {
controller.changeState(Running);
};
_Start.prototype.start.transitions = ['Running'];
_Running.prototype.start = function (controller) {
controller.scope.interval = setInterval(function () {
controller.scope.frame_number = controller.scope.frame_number_seq();
if (!controller.scope.active) {
return;
}
if (controller.scope.frame_number > controller.scope.steps) {
controller.scope.fsm.handle_message('AnimationCompleted');
return;
}
controller.scope.callback(controller.scope);
controller.scope.scope.$apply();
}, 17);
};
_Running.prototype.onAnimationCancelled = function (controller) {
controller.changeState(Cancelled);
};
_Running.prototype.onAnimationCancelled.transitions = ['Cancelled'];
_Running.prototype.onAnimationCompleted = function (controller) {
controller.changeState(Completed);
};
_Running.prototype.onAnimationCompleted.transitions = ['Completed'];
_Completed.prototype.start = function (controller) {
controller.scope.active = false;
clearInterval(controller.scope.interval);
};
_Cancelled.prototype.start = function (controller) {
controller.scope.active = false;
clearInterval(controller.scope.interval);
};

View File

@ -0,0 +1,51 @@
/*
* Uses y = cx^2 * cdx to calculate the height of the camera
* Uses scale = 1 / (height + 1) to calculate the scale of the virtual canvas
*/
function scale_animation (scope) {
var d = scope.steps;
var c = scope.data.c;
var x = scope.frame_number;
var initial_height = ((1 / scope.data.current_scale) - 1);
var a = -1 * initial_height / (c * d);
var height = 0;
if(scope.data.distance > 0) {
height = (x + a) * (x - d) * c + scope.data.end_height;
} else {
height = (scope.data.end_height - initial_height) * (scope.frame_number / scope.steps) + initial_height
}
//console.log({x: x,
// c: c,
// d: d,
// a: a,
// h: height,
// i: initial_height});
scope.data.scope.current_scale = 1 / (1 + height);
//console.log(scope.data.scope.current_scale);
//scope.data.scope.current_scale = 1.0;
scope.data.scope.first_channel.send("ScaleChanged", {});
scope.data.scope.first_channel.send("ScaleChanged", {});
scope.data.scope.updatePanAndScale();
}
exports.scale_animation = scale_animation;
function pan_animation (scope) {
var incr_x = (scope.data.x2 - scope.data.x1) / scope.steps;
var incr_y = (scope.data.y2 - scope.data.y1) / scope.steps;
//console.log({incr_x: incr_x, incr_y: incr_y});
var v_x = incr_x * scope.frame_number + scope.data.x1;
var v_y = incr_y * scope.frame_number + scope.data.y1;
var p = scope.data.scope.to_pan(v_x, v_y);
//console.log({v_x: v_x, v_y: v_y});
//console.log({p_x: p.x, p_y: p.y});
//scope.data.scope.panX = scope.data.scope.graph.width/2 - scope.data.scope.current_scale * p.x / 1.0;
//scope.data.scope.panY = scope.data.scope.graph.height/2 - scope.data.scope.current_scale * p.y / 1.0;
scope.data.scope.panX = p.x + scope.data.scope.graph.width/2;
scope.data.scope.panY = p.y + scope.data.scope.graph.height/2;
scope.data.scope.first_channel.send("PanChanged", {});
scope.data.scope.updatePanAndScale();
}
exports.pan_animation = pan_animation;

View File

@ -1,7 +1,8 @@
<!-- Copyright (c) 2017 Red Hat, Inc. -->
<g ng-attr-class="{{debug.hidden && 'NetworkUI--hidden' || ''}}">
<g ng-attr-class="{{debug.hidden && 'NetworkUI--hidden' || ''}}">
<g transform="translate(0, 100)">
<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>
@ -45,5 +46,16 @@
<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>
</g>
<rect x=10 y=10 ng-attr-width="{{graph.width - 20}}" ng-attr-height="{{graph.height - 20}}" class="NetworkUI--debug"></rect>
<line x1="-10000"
ng-attr-y1="{{graph.height/2}}"
x2="10000"
ng-attr-y2="{{graph.height/2}}"
ng-attr-class="{{debug.hidden && 'NetworkUI--hidden' || 'NetworkUI--debug'}}" />
<line ng-attr-x1="{{graph.width/2}}"
y1="-10000"
ng-attr-x2="{{graph.width/2}}"
y2="10000"
ng-attr-class="{{debug.hidden && 'NetworkUI--hidden' || 'NetworkUI--debug'}}" />
</g>

View File

@ -77,8 +77,13 @@ _Enabled.prototype.onKeyDown = function(controller, msg_type, $event) {
scope.hide_interfaces = !scope.hide_interfaces;
return;
}
if($event.keyCode === 27){
// 27 is the escape key
scope.reset_fsm_state();
return;
}
if ($event.key === 'r') {
if ($event.key === 'r' && !($event.ctrlKey || $event.metaKey)) {
scope.first_channel.send("NewDevice", new messages.NewDevice("router"));
return;
}
@ -103,11 +108,7 @@ _Enabled.prototype.onKeyDown = function(controller, msg_type, $event) {
return;
}
else if ($event.key === '0') {
scope.panX = 0;
scope.panY = 0;
scope.current_scale = 1.0;
scope.updateScaledXY();
scope.updatePanAndScale();
scope.jump_to_animation(0, 0, 1.0);
}
controller.delegate_channel.send(msg_type, $event);

View File

@ -0,0 +1,59 @@
var inherits = require('inherits');
var fsm = require('./fsm.js');
function _State () {
}
inherits(_State, fsm._State);
function _Disabled () {
this.name = 'Disabled';
}
inherits(_Disabled, _State);
var Disabled = new _Disabled();
exports.Disabled = Disabled;
function _Start () {
this.name = 'Start';
}
inherits(_Start, _State);
var Start = new _Start();
exports.Start = Start;
function _Enabled () {
this.name = 'Enabled';
}
inherits(_Enabled, _State);
var Enabled = new _Enabled();
exports.Enabled = Enabled;
_Disabled.prototype.onBindDocument = function (controller) {
$(document).bind("keydown", controller.scope.onKeyDown);
controller.changeState(Enabled);
};
_Disabled.prototype.onBindDocument.transitions = ['Enabled'];
_Start.prototype.start = function (controller) {
$(document).bind("keydown", controller.scope.onKeyDown);
controller.changeState(Enabled);
};
_Start.prototype.start.transitions = ['Enabled'];
_Enabled.prototype.onUnbindDocument = function (controller) {
$(document).unbind("keydown", controller.scope.onKeyDown);
controller.changeState(Disabled);
};
_Enabled.prototype.onUnbindDocument.transitions = ['Disabled'];

View File

@ -88,6 +88,8 @@ _Interface.prototype.onMouseWheel = function (controller, msg_type, $event) {
};
_Interface.prototype.onMouseWheel.transitions = ['Device'];
_Interface.prototype.onScaleChanged = _Interface.prototype.onMouseWheel;
_Site.prototype.start = function (controller) {
controller.scope.current_mode = controller.state.name;
controller.scope.rack_toolbox_controller.handle_message('Enable', {});
@ -115,6 +117,7 @@ _Site.prototype.onMouseWheel = function (controller, msg_type, $event) {
};
_Site.prototype.onMouseWheel.transitions = ['MultiSite', 'Rack'];
_Site.prototype.onScaleChanged = _Site.prototype.onMouseWheel;
_Process.prototype.onMouseWheel = function (controller, msg_type, $event) {
@ -126,6 +129,8 @@ _Process.prototype.onMouseWheel = function (controller, msg_type, $event) {
};
_Process.prototype.onMouseWheel.transitions = ['Device'];
_Process.prototype.onScaleChanged = _Process.prototype.onMouseWheel;
_MultiSite.prototype.start = function (controller) {
controller.scope.current_mode = controller.state.name;
controller.scope.site_toolbox_controller.handle_message('Enable', {});
@ -149,6 +154,8 @@ _MultiSite.prototype.onMouseWheel = function (controller, msg_type, $event) {
};
_MultiSite.prototype.onMouseWheel.transitions = ['Site'];
_MultiSite.prototype.onScaleChanged = _MultiSite.prototype.onMouseWheel;
_Device.prototype.start = function (controller) {
controller.scope.current_mode = controller.state.name;
controller.scope.app_toolbox_controller.handle_message('Enable', {});
@ -175,6 +182,7 @@ _Device.prototype.onMouseWheel = function (controller, msg_type, $event) {
};
_Device.prototype.onMouseWheel.transitions = ['Process', 'Interface', 'Rack'];
_Device.prototype.onScaleChanged = _Device.prototype.onMouseWheel;
_Rack.prototype.start = function (controller) {
controller.scope.current_mode = controller.state.name;
@ -203,3 +211,5 @@ _Rack.prototype.onMouseWheel = function (controller, msg_type, $event) {
controller.delegate_channel.send(msg_type, $event);
};
_Rack.prototype.onMouseWheel.transitions = ['Site', 'Device'];
_Rack.prototype.onScaleChanged = _Rack.prototype.onMouseWheel;

View File

@ -1,8 +1,9 @@
/* Copyright (c) 2017 Red Hat, Inc. */
/* Copyright (c) 2017-2018 Red Hat, Inc. */
var fsm = require('./fsm.js');
var button = require('./button.js');
var util = require('./util.js');
var inherits = require('inherits');
var animation_fsm = require('./animation.fsm.js');
function Device(id, name, x, y, type, host_id) {
this.id = id;
@ -908,3 +909,18 @@ function TestResult(id, name, result, date, code_under_test) {
this.code_under_test = code_under_test;
}
exports.TestResult = TestResult;
function Animation(id, steps, data, scope, tracer, callback) {
this.id = id;
this.steps = steps;
this.active = true;
this.frame_number_seq = util.natural_numbers(-1);
this.frame_number = 0;
this.data = data;
this.callback = callback;
this.scope = scope;
this.interval = null;
this.fsm = new fsm.FSMController(this, "animation_fsm", animation_fsm.Start, tracer);
}
exports.Animation = Animation;

View File

@ -139,6 +139,7 @@ _Ready.prototype.onNewDevice = function (controller, msg_type, message) {
device.host_id));
scope.selected_devices.push(device);
device.selected = true;
scope.$emit('addSearchOption', device);
controller.changeState(Placing);
}
};
@ -451,6 +452,7 @@ _EditLabel.prototype.onKeyDown = function (controller, msg_type, $event) {
} else if ($event.keyCode >= 186 && $event.keyCode <=222) { //Punctuation
item.name += $event.key;
} else if ($event.keyCode === 13) { //Enter
controller.scope.$emit('editSearchOption', item);
controller.changeState(Selected2);
}
if (item.constructor.name === "Device") {

View File

@ -190,7 +190,14 @@
}
.Networking-searchBarContainer{
height: 30px
height: 30px;
flex: 1 0 auto;
display: flex;
margin-top:-5px;
}
.Networking-dropDown{
left:-2px!important;
}
.Networking-searchButton{

View File

@ -1,9 +1,9 @@
import NetworkingController from './networking.controller';
import NetworkingStrings from './networking.strings';
import NetworkingController from './network.nav.controller';
import NetworkingStrings from './network.nav.strings';
const MODULE_NAME = 'at.features.networking';
const networkingTemplate = require('~features/networking/networking.view.html');
const networkNavTemplate = require('~network-ui/network-nav/network.nav.view.html');
function NetworkingResolve ($stateParams, resourceData) {
const resolve = {
@ -31,7 +31,7 @@ function NetworkingRun ($stateExtender, strings) {
},
views: {
'networking@': {
templateUrl: networkingTemplate,
templateUrl: networkNavTemplate,
controller: NetworkingController,
controllerAs: 'vm'
}

View File

@ -0,0 +1,136 @@
/* eslint-disable */
function NetworkingController (models, $state, $scope, strings, CreateSelect2) {
const vm = this || {};
const {
inventory
} = models;
vm.strings = strings;
vm.panelTitle = `${strings.get('state.BREADCRUMB_LABEL')} | ${inventory.name}`;
vm.hostDetail = {};
vm.rightPanelIsExpanded = false;
vm.leftPanelIsExpanded = true;
vm.jumpToPanelExpanded = false;
vm.keyPanelExpanded = false;
$scope.devices = [];
// $scope.device = null;
vm.close = () => {
$state.go('inventories');
};
vm.redirectButtonHandler = (string) => {
$scope.$broadcast('toolbarButtonEvent', string);
};
vm.jumpTo = (thing) => {
vm.jumpToPanelExpanded = !vm.jumpToPanelExpanded;
vm.keyPanelExpanded = false;
if (thing && typeof thing === 'string') {
$scope.$broadcast('jumpTo', thing);
}
if (thing && typeof thing === 'object') {
$scope.$broadcast('search', thing);
}
};
vm.key = () => {
vm.keyPanelExpanded = !vm.keyPanelExpanded;
vm.jumpToPanelExpanded = false;
};
$scope.$on('overall_toolbox_collapsed', () => {
vm.leftPanelIsExpanded = !vm.leftPanelIsExpanded;
});
$scope.$on('closeDetailsPanel', () => {
vm.rightPanelIsExpanded = false;
vm.jumpToPanelExpanded = false;
vm.keyPanelExpanded = false;
});
$scope.$on('showDetails', (e, data, expand) => {
if (expand) {
vm.rightPanelIsExpanded = true;
}
if (!_.has(data, 'host_id')) {
$scope.item = data;
} else {
$scope.item = data;
}
});
$scope.$on('instatiateSelect', (e, devices) => {
for(var i = 0; i < devices.length; i++){
let device = devices[i];
$scope.devices.push({
value: device.id,
text: device.name,
label: device.name,
id: device.id
});
}
$("#networking-search").select2({
width:'100%',
containerCssClass: 'Form-dropDown',
placeholder: 'SEARCH'
});
});
$scope.$on('addSearchOption', (e, device) => {
$scope.devices.push({
value: device.id,
text: device.name,
label: device.name,
id: device.id
});
});
$scope.$on('editSearchOption', (e, device) => {
for(var i = 0; i < $scope.devices.length; i++){
if(device.id === $scope.devices[i].id){
$scope.devices[i].text = device.name;
$scope.devices[i].label = device.name;
}
}
});
$scope.$on('removeSearchOption', (e, device) => {
for (var i = 0; i < $scope.devices.length; i++) {
if ($scope.devices[i].id === device.id) {
$scope.devices.splice(i, 1);
}
}
});
$('#networking-search').on('select2:select', (e) => {
$scope.$broadcast('search', e.params.data);
});
$('#networking-search').on('select2:open', () => {
$('.select2-dropdown').addClass('Networking-dropDown');
$scope.$broadcast('unbind');
});
$('#networking-search').on('select2:close', () => {
setTimeout(function() {
$('.select2-container-active').removeClass('select2-container-active');
$(':focus').blur();
}, 1);
$scope.$broadcast('bind');
});
}
NetworkingController.$inject = [
'resolvedModels',
'$state',
'$scope',
'NetworkingStrings',
'CreateSelect2'
];
export default NetworkingController;
/* eslint-disable */

View File

@ -22,14 +22,13 @@
<button class="Networking-toolbarButton" ng-click="vm.redirectButtonHandler('RunTests')">RUN TESTS</button>
</div>
<div class="Networking-toolbarRightSide">
<div class="SmartSearch-searchTermContainer Networking-searchBarContainer">
<!-- string search input -->
<form name="smartSearch" class="SmartSearch-form ng-pristine ng-valid" aw-enter-key="addTerm(searchTerm)" novalidate="">
<input class="SmartSearch-input ng-pristine ng-valid ng-empty ng-touched" ng-model="searchTerm" placeholder="Search" ng-disabled="disableSearch">
</form>
<div type="submit" class="SmartSearch-searchButton Networking-searchButton" ng-disabled="!searchTerm" ng-click="addTerm(searchTerm)" disabled="disabled">
<i class="fa fa-search"></i>
</div>
<div class="Networking-searchBarContainer">
<select id="networking-search" ng-model="device" ng-options="device.label for device in devices track by device.id">
<option></option>
</select>
<!-- <select id="networking-search" style="width:100%"><option></option></select> -->
<!-- <select class="Form-dropDown" id="networking-search"> -->
<!-- <option ng-repeat="device in devices" value="{{device.id}}">{{device.name}}</option> -->
</div>
<div class="Networking-keyContainer">
<button ng-click="vm.key()" type="button" class="Networking-toolbarIcon" ng-class="{'Networking-toolbarIcon--selected' : vm.keyPanelExpanded}">
@ -118,9 +117,9 @@
</div>
</div>
<div class="Networking-toolbar Networking-breadCrumbBar">
<div class="Networking-breadCrumbText">foo-bar</div>
<div class="Networking-breadCrumbText"></div>
</div>
</div>
</div>
@ -144,6 +143,17 @@
</div>
<!--end of name row -->
<!--beginning of name row -->
<div class="JobResults-resultRow" ng-if="item.host_id">
<label class="JobResults-resultRowLabel Networking-resultRowLabel" translate="">
Description
</label>
<input class="JobResults-resultRowText">
</input>
</div>
<!--end of name row -->
<div class="List-noItems Networking-noItems" ng-if="!item.host_id">
{{item.type}} DETAILS NOT AVAILABLE
</div>

View File

@ -1,5 +1,7 @@
/* Copyright (c) 2017 Red Hat, Inc. */
import atFeaturesNetworking from './network-nav/index';
//console.log = function () { };
var angular = require('angular');
var NetworkUIController = require('./network.ui.controller.js');
@ -31,6 +33,7 @@ var awxNetworkUI = require('./network.ui.directive.js');
var networkUI = angular.module('networkUI', [
'monospaced.mousewheel',
atFeaturesNetworking
])
.controller('NetworkUIController', NetworkUIController.NetworkUIController)
.directive('awxNetCursor', cursor.cursor)

View File

@ -19,6 +19,8 @@ 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 svg_crowbar = require('./svg-crowbar.js');
var ReconnectingWebSocket = require('reconnectingwebsocket');
@ -106,6 +108,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.message_id_seq = util.natural_numbers(0);
$scope.stream_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;
@ -124,6 +127,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.test_results = [];
$scope.test_errors = [];
$scope.streams = [];
$scope.animations = [];
$scope.view_port = {'x': 0,
'y': 0,
'width': 0,
@ -131,6 +135,10 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$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.send_trace_message = function (message) {
if (!$scope.recording) {
@ -150,9 +158,30 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
}
};
$scope.onKeyDown = function ($event) {
if ($scope.recording) {
$scope.send_control_message(new messages.KeyEvent($scope.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.null_controller = new fsm.FSMController($scope, "null_fsm", null_fsm.Start, $scope);
$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.device_detail_controller = new fsm.FSMController($scope, "device_detail_fsm", device_detail_fsm.Start, $scope);
$scope.move_controller = new fsm.FSMController($scope, "move_fsm", move.Start, $scope);
@ -202,21 +231,28 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
.then(function(response) {
let hosts = response.data.results;
for(var i = 0; i<hosts.length; i++){
let host = hosts[i];
console.log(host);
host.data = jsyaml.safeLoad(host.variables);
if (host.data.type == undefined) {
host.data.type = 'unknown';
try {
let host = hosts[i];
console.log(host);
if (host.variables !== "") {
host.data = jsyaml.safeLoad(host.variables);
if (host.data.type === undefined) {
host.data.type = 'unknown';
}
if (host.data.name === undefined) {
host.data.name = host.name;
}
var device = new models.Device(0, host.data.name, 0, 0, host.data.type, host.id, host.variables);
device.icon = true;
$scope.inventory_toolbox.items.push(device);
}
} catch (error) {
console.log(error);
}
if (host.data.name == undefined) {
host.data.name = host.name;
}
var device = new models.Device(0, host.data.name, 0, 0, host.data.type, host.id, host.variables);
device.icon = true;
$scope.inventory_toolbox.items.push(device);
}
})
.catch(({data, status}) => {
console.log([data, status]);
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get host data: ' + status });
});
}
@ -269,9 +305,13 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.mode_controller = new fsm.FSMController($scope, "mode_fsm", mode_fsm.Start, $scope);
//Wire up the FSMs
$scope.view_controller.delegate_channel = new fsm.Channel($scope.view_controller,
$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);
$scope.device_detail_controller.delegate_channel = new fsm.Channel($scope.device_detail_controller,
$scope.view_controller,
$scope);
@ -354,6 +394,24 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
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_browser_coordinates = function (v_x, v_y) {
var b_x = (v_x * $scope.current_scale) + $scope.panX;
var b_y = (v_y * $scope.current_scale) + $scope.panY;
return {x: b_x, y: b_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;
@ -565,41 +623,22 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$event.preventDefault();
};
$scope.onKeyDown = function ($event) {
if ($scope.recording) {
$scope.send_control_message(new messages.KeyEvent($scope.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();
};
$document.bind("keydown", $scope.onKeyDown);
// 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, index){
context_menu.buttons.forEach(function(button){
button.enabled = false;
button.x = -100000;
button.y = -100000;
});
}
};
$scope.closeDetailsPanel = function () {
$scope.$emit('closeDetailsPanel');
};
$scope.onDetailsContextButton = function (panelBoolean) {
if (!$scope.disconnected) {
@ -689,6 +728,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
index = $scope.devices.indexOf(devices[i]);
if (index !== -1) {
$scope.devices.splice(index, 1);
$scope.$emit('removeSearchOption', devices[i]);
$scope.send_control_message(new messages.DeviceDestroy($scope.client_id,
devices[i].id,
devices[i].x,
@ -790,29 +830,85 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope[`on${functionName}Button`]();
});
$scope.$on('jumpTo', function(e, zoomLevel){
$scope.$on('unbind', function(){
$scope.first_channel.send('UnbindDocument', {});
});
$scope.$on('bind', function(){
$scope.first_channel.send('BindDocument', {});
});
$scope.jump_to_animation = function(jump_to_x, jump_to_y, jump_to_scale) {
$scope.cancel_animations();
var v_center = $scope.to_virtual_coordinates($scope.graph.width/2, $scope.graph.height/2);
//console.log({v_center: v_center});
$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);
//console.log({distance: distance});
var num_frames = 30 * Math.floor((1 + 4 * distance / (distance + 3000)));
//console.log({num_frames: num_frames});
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
},
$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('search', function(e, device){
var num_frames = 30;
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);
//console.log(searched);
$scope.jump_to_animation(searched.x, searched.y, 1.0);
});
$scope.$on('jumpTo', function(e, zoomLevel) {
var v_center = $scope.to_virtual_coordinates($scope.graph.width/2, $scope.graph.height/2);
switch (zoomLevel){
case 'site':
$scope.current_scale = 0.051;
$scope.jump_to_animation(v_center.x, v_center.y, 0.051);
break;
case 'rack':
$scope.current_scale = 0.11;
$scope.jump_to_animation(v_center.x, v_center.y, 0.11);
break;
case 'inventory':
$scope.current_scale = 0.51;
$scope.jump_to_animation(v_center.x, v_center.y, 0.51);
break;
case 'process':
$scope.current_scale = 1.1;
$scope.jump_to_animation(v_center.x, v_center.y, 5.1);
break;
}
// var new_panX = controller.scope.{{somethinghere}} - 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();
// // controller.scope.current_scale = new_scale;
// controller.scope.panX = new_panX;
// controller.scope.panY = new_panY;
$scope.updateScaledXY();
$scope.updatePanAndScale();
});
$scope.onDeployButton = function (button) {
@ -1691,6 +1787,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
}
$scope.updateInterfaceDots();
$scope.$emit('instatiateSelect', $scope.devices);
};
$scope.updateInterfaceDots = function() {
@ -1774,7 +1871,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.$on('$destroy', function () {
console.log("Network UI stopping");
$document.unbind('keydown', $scope.onKeyDown);
$scope.first_channel.send('UnbindDocument', {});
});
$scope.update_toolbox_heights = function(){
@ -1877,6 +1974,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.null_controller.state.start($scope.null_controller);
$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.device_detail_controller.state = device_detail_fsm.Start;
@ -1927,6 +2026,15 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.rack_toolbox.items = [];
$scope.site_toolbox.items = [];
};
$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;

View File

@ -85,7 +85,7 @@
</g>
<g awx-net-quadrants>
</g>
</g>
</g> <!-- end frame_g -->
<g ng-repeat="toolbox in [site_toolbox, rack_toolbox, inventory_toolbox, app_toolbox]">
<g awx-net-inventory-toolbox></g>
</g>

View File

@ -1,17 +1,27 @@
<!-- Copyright (c) 2017 Red Hat, Inc. -->
<line x1="-100000"
y1="0"
x2="100000"
y2="0"
ng-attr-class="{{debug.hidden && 'NetworkUI--hidden' || 'NetworkUI--debug'}}" />
<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>
<g ng-attr-transform="scale({{1/(current_scale)}})">
<line x1="-10000"
y1="0"
x2="10000"
y2="0"
ng-attr-class="{{debug.hidden && 'NetworkUI--hidden' || 'NetworkUI--debug'}}" />
<line x1="0"
y1="-10000"
x2="0"
y2="10000"
ng-attr-class="{{debug.hidden && 'NetworkUI--hidden' || 'NetworkUI--debug'}}" />
</g>
<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>
<g ng-if="!debug.hidden">
<line ng-attr-x1="{{jump.from_x}}"
ng-attr-y1="{{jump.from_y}}"
ng-attr-x2="{{jump.to_x}}"
ng-attr-y2="{{jump.to_y}}"
stroke="#4dc8f2"
ng-attr-stroke-width="{{10/current_scale}}" />
</g>

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2017 Red Hat, Inc. */
@import 'network-nav/_index';
@font-face {
font-family: 'Open Sans';
font-style: normal;

View File

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