Adds editing to the host details form.

* Adds editing host vars, description, and name to the host details
form.
* Adds details panel FSM and updates to keybindings FSM
This commit is contained in:
Jared Tabor
2018-02-12 20:42:46 -08:00
committed by Ben Thomasson
parent 6f3bf4fd1b
commit 14ee6a8360
34 changed files with 954 additions and 493 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -0,0 +1,25 @@
diagram_id: 70
name: diagram
states:
- id: 1
label: Start
x: 590
y: 233
- id: 2
label: Collapsed
x: 594
y: 490
- id: 3
label: Expanded
x: 919
y: 491
transitions:
- from_state: Start
label: start
to_state: Collapsed
- from_state: Expanded
label: onDetailsPanelClose
to_state: Collapsed
- from_state: Collapsed
label: onDetailsPanel
to_state: Expanded

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 161 KiB

View File

@@ -1,7 +1,7 @@
diagram_id: 60
diagram_id: 68
name: diagram
states:
- id: 3
- id: 1
label: Enabled
x: 842
y: 533
@@ -9,10 +9,10 @@ states:
label: Start
x: 839
y: 270
- id: 6
- id: 3
label: Disabled
x: 1231
y: 532
x: 1412
y: 522
transitions:
- from_state: Start
label: start
@@ -23,3 +23,15 @@ transitions:
- from_state: Enabled
label: onUnbindDocument
to_state: Disabled
- from_state: Disabled
label: onDetailsPanelClose
to_state: Enabled
- from_state: Enabled
label: onDetailsPanel
to_state: Disabled
- from_state: Enabled
label: onSearchDropdown
to_state: Disabled
- from_state: Disabled
label: onSearchDropdownClose
to_state: Enabled

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 271 KiB

View File

@@ -1,94 +1,107 @@
finite_state_machine_id: 13
name: move_fsm
diagram_id: 64
name: move
states:
- id: 9
- id: 1
label: Disable
x: 743
y: 108
- id: 1
- id: 2
label: Start
x: 533
y: 121
- id: 2
- id: 3
label: Ready
x: 531
y: 320
- id: 3
- id: 4
label: Selected1
x: 226
y: 325
- id: 4
label: Selected2
x: 230
y: 582
- id: 5
- id: 6
label: Move
x: -54
y: 587
- id: 6
label: EditLabel
x: 566
y: 677
- id: 7
label: Selected3
x: 175
y: 886
- id: 8
label: Placing
x: 92
y: 82
- id: 9
label: EditLabel
x: 594
y: 677
- id: 5
label: Selected2
x: 275
y: 682
- id: 10
label: ContextMenu
x: 901
y: 990
- id: 7
label: Selected3
x: 190
y: 954
transitions:
- from_state: Selected2
label: onKeyDown
to_state: Ready
- from_state: Selected2
label: onNewDevice
to_state: Ready
- from_state: EditLabel
label: onMouseDown
to_state: Ready
- from_state: Selected2
- from_state: ContextMenu
label: onDetailsPanel
to_state: Selected2
- from_state: ContextMenu
label: onMouseDown
to_state: Ready
- from_state: Start
label: start
to_state: Ready
- from_state: Move
- from_state: Selected2
label: onMouseDown
to_state: Selected1
- from_state: Placing
to_state: Ready
- from_state: EditLabel
label: onMouseDown
to_state: Ready
- from_state: Selected2
label: onNewDevice
to_state: Ready
- from_state: Selected2
label: onKeyDown
to_state: Ready
- from_state: Ready
label: onMouseDown
to_state: Selected1
- from_state: Move
label: onMouseUp
to_state: Selected1
- from_state: Ready
- from_state: Placing
label: onMouseDown
to_state: Selected1
- from_state: Ready
label: onPasteDevice
- from_state: Move
label: onMouseDown
to_state: Selected1
- from_state: Selected1
label: onMouseUp
to_state: Selected2
- from_state: EditLabel
label: onKeyDown
to_state: Selected2
- from_state: Selected1
label: onMouseUp
- from_state: Ready
label: onPasteDevice
to_state: Selected2
- from_state: Selected1
label: onMouseMove
to_state: Move
- from_state: Selected3
label: onMouseMove
to_state: Move
- from_state: Placing
label: onMouseMove
to_state: Move
- from_state: Selected3
label: onMouseMove
to_state: Move
- from_state: Selected1
label: onMouseMove
to_state: Move
- from_state: Selected3
label: onMouseUp
to_state: EditLabel
- from_state: Selected2
label: onMouseDown
to_state: Selected3
- from_state: Ready
label: onNewDevice
to_state: Placing
- from_state: ContextMenu
label: onLabelEdit
to_state: EditLabel
- from_state: Selected3
label: onMouseUp
to_state: ContextMenu

View File

@@ -29,6 +29,7 @@ function scale_animation (scope) {
scope.data.scope.first_channel.send("ScaleChanged", {});
scope.data.scope.first_channel.send("ScaleChanged", {});
scope.data.scope.updatePanAndScale();
scope.data.scope.$emit('awxNet-UpdateZoomWidget', scope.data.scope.current_scale, scope.data.updateZoomBoolean);
}
exports.scale_animation = scale_animation;

View File

@@ -0,0 +1,63 @@
var inherits = require('inherits');
var fsm = require('./fsm.js');
function _State () {
}
inherits(_State, fsm._State);
function _Start () {
this.name = 'Start';
}
inherits(_Start, _State);
var Start = new _Start();
exports.Start = Start;
function _Collapsed () {
this.name = 'Collapsed';
}
inherits(_Collapsed, _State);
var Collapsed = new _Collapsed();
exports.Collapsed = Collapsed;
function _Expanded () {
this.name = 'Expanded';
}
inherits(_Expanded, _State);
var Expanded = new _Expanded();
exports.Expanded = Expanded;
_Start.prototype.start = function (controller, msg_type, $event) {
controller.scope.$parent.vm.rightPanelIsExpanded = false;
controller.changeState(Collapsed);
controller.handle_message(msg_type, $event);
};
_Start.prototype.start.transitions = ['Collapsed'];
_Collapsed.prototype.onDetailsPanel = function (controller, msg_type, $event) {
controller.scope.$parent.vm.rightPanelIsExpanded = true;
controller.changeState(Expanded);
controller.handle_message(msg_type, $event);
};
_Collapsed.prototype.onDetailsPanel.transitions = ['Expanded'];
_Expanded.prototype.onDetailsPanelClose = function (controller, msg_type, $event) {
controller.scope.$parent.vm.rightPanelIsExpanded = false;
controller.scope.$parent.vm.jumpToPanelExpanded = false;
controller.scope.$parent.vm.keyPanelExpanded = false;
controller.changeState(Collapsed);
controller.handle_message(msg_type, $event);
};
_Expanded.prototype.onDetailsPanelClose.transitions = ['Collapsed'];

View File

@@ -1,89 +1,91 @@
<!-- Copyright (c) 2017 Red Hat, Inc. -->
<g transform="scale(0.75)">
<g ng-if="item.moving">
<!--horizontal line -->
<line x1="-150"
y1="0"
x2="150"
y2="0"
class="NetworkUI--construction">
</line>
<!-- end horizontal line -->
<g ng-if="item.icon || (current_scale > 0.5 && current_scale < 5) || !item.in_group">
<g transform="scale(0.75)">
<g ng-if="item.moving">
<!--horizontal line -->
<line x1="-150"
y1="0"
x2="150"
y2="0"
class="NetworkUI--construction">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-150"
x2="0"
y2="150"
class="NetworkUI--construction">
</line>
<!-- end vertical line -->
</g>
<!-- vertical line -->
<line x1="0"
y1="-150"
x2="0"
y2="150"
class="NetworkUI--construction">
</line>
<!-- end vertical line -->
</g>
<g ng-if="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<g ng-if="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-40"
x2="0"
y2="40"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- vertical line -->
<line x1="0"
y1="-40"
x2="0"
y2="40"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- debug rectangle -->
<rect x="-50"
y="-30"
width="100"
height="60"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<g transform="translate(-50,-30)">
<rect
ry=20
rx=20
width=100
height=60
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__host--selected-conflict' : item.selected ? 'NetworkUI__host--selected' : 'NetworkUI__host--remote-selected' : 'NetworkUI__host--background'}}">
</rect>
<g transform="scale(2)">
<path
class="NetworkUI__host"
d="M17.8,14.7c-0.3,0-0.6,0.2-0.6,0.6c0,0.3,0.2,0.6,0.6,0.6c0.3,0,0.6-0.2,0.6-0.6S18.1,14.7,17.8,14.7z"/>
<path
class="NetworkUI__host"
d="M40.8,0H9.2C4.2,0,0,4.2,0,9.2v11.5C0,25.8,4.2,30,9.2,30h31.5c5.1,0,9.2-4.2,9.2-9.2V9.2
C50,4.2,45.8,0,40.8,0z M37.8,17.9c0,1-0.8,1.8-1.8,1.8H14c-1,0-1.8-0.8-1.8-1.8V13c0-1,0.8-1.8,1.8-1.8h22c1,0,1.8,0.8,1.8,1.8
V17.9z"/>
<path
class="NetworkUI__host"
d="M36,12.5H14c-0.3,0-0.4,0.2-0.4,0.4v4.9c0,0.3,0.2,0.4,0.4,0.4h22c0.3,0,0.4-0.2,0.4-0.4v-4.9
C36.4,12.7,36.3,12.5,36,12.5z M17.8,17.2c-1.1,0-1.9-0.9-1.9-1.9c0-1.1,0.9-1.9,1.9-1.9s1.9,0.9,1.9,1.9S18.9,17.2,17.8,17.2z
M28.2,17.1h-0.9c-0.3,0-0.6-0.2-0.6-0.6s0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,16.8,28.6,17.1,28.2,17.1z M28.2,14.9
h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,14.7,28.6,14.9,28.2,14.9z M30.9,17.1H30
c-0.3,0-0.6-0.2-0.6-0.6s0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C31.5,16.8,31.3,17.1,30.9,17.1z M30.9,14.9H30
c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6S31.3,14.9,30.9,14.9z M33.6,17.1h-0.9
c-0.4,0-0.6-0.2-0.6-0.6s0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,16.8,33.9,17.1,33.6,17.1z M33.6,14.9h-0.9
c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,14.7,33.9,14.9,33.6,14.9z"/>
<!-- debug rectangle -->
<rect x="-50"
y="-30"
width="100"
height="60"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<g transform="translate(-50,-30)">
<rect
ry=20
rx=20
width=100
height=60
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__host--selected-conflict' : item.selected ? 'NetworkUI__host--selected' : 'NetworkUI__host--remote-selected' : 'NetworkUI__host--background'}}">
</rect>
<g transform="scale(2)">
<path
class="NetworkUI__host"
d="M17.8,14.7c-0.3,0-0.6,0.2-0.6,0.6c0,0.3,0.2,0.6,0.6,0.6c0.3,0,0.6-0.2,0.6-0.6S18.1,14.7,17.8,14.7z"/>
<path
class="NetworkUI__host"
d="M40.8,0H9.2C4.2,0,0,4.2,0,9.2v11.5C0,25.8,4.2,30,9.2,30h31.5c5.1,0,9.2-4.2,9.2-9.2V9.2
C50,4.2,45.8,0,40.8,0z M37.8,17.9c0,1-0.8,1.8-1.8,1.8H14c-1,0-1.8-0.8-1.8-1.8V13c0-1,0.8-1.8,1.8-1.8h22c1,0,1.8,0.8,1.8,1.8
V17.9z"/>
<path
class="NetworkUI__host"
d="M36,12.5H14c-0.3,0-0.4,0.2-0.4,0.4v4.9c0,0.3,0.2,0.4,0.4,0.4h22c0.3,0,0.4-0.2,0.4-0.4v-4.9
C36.4,12.7,36.3,12.5,36,12.5z M17.8,17.2c-1.1,0-1.9-0.9-1.9-1.9c0-1.1,0.9-1.9,1.9-1.9s1.9,0.9,1.9,1.9S18.9,17.2,17.8,17.2z
M28.2,17.1h-0.9c-0.3,0-0.6-0.2-0.6-0.6s0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,16.8,28.6,17.1,28.2,17.1z M28.2,14.9
h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,14.7,28.6,14.9,28.2,14.9z M30.9,17.1H30
c-0.3,0-0.6-0.2-0.6-0.6s0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C31.5,16.8,31.3,17.1,30.9,17.1z M30.9,14.9H30
c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6S31.3,14.9,30.9,14.9z M33.6,17.1h-0.9
c-0.4,0-0.6-0.2-0.6-0.6s0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,16.8,33.9,17.1,33.6,17.1z M33.6,14.9h-0.9
c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,14.7,33.9,14.9,33.6,14.9z"/>
</g>
</g>
<g>
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__host-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#background)"
text-anchor="middle"
x="0"
y="50"> {{item.name}}
</text>
<text class="NetworkUI__host-text" filter="url(#background)" text-anchor="middle" x="0" y="50">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
</g>
<g ng-show="item.icon || current_scale > 0.5">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__host-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#background)"
text-anchor="middle"
x="0"
y="50"> {{item.name}}
</text>
<text class="NetworkUI__host-text" filter="url(#background)" text-anchor="middle" x="0" y="50">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
</g>

View File

@@ -57,3 +57,37 @@ _Enabled.prototype.onUnbindDocument = function (controller) {
};
_Enabled.prototype.onUnbindDocument.transitions = ['Disabled'];
_Disabled.prototype.onDetailsPanelClose = function (controller) {
$(document).bind("keydown", controller.scope.onKeyDown);
controller.changeState(Enabled);
};
_Disabled.prototype.onDetailsPanelClose.transitions = ['Enabled'];
_Disabled.prototype.onSearchDropdownClose = function (controller) {
$(document).bind("keydown", controller.scope.onKeyDown);
controller.changeState(Enabled);
};
_Disabled.prototype.onSearchDropdownClose.transitions = ['Enabled'];
_Enabled.prototype.onDetailsPanel = function (controller) {
$(document).unbind("keydown", controller.scope.onKeyDown);
controller.changeState(Disabled);
};
_Enabled.prototype.onDetailsPanel.transitions = ['Disabled'];
_Enabled.prototype.onSearchDropdown = function (controller) {
$(document).unbind("keydown", controller.scope.onKeyDown);
controller.changeState(Disabled);
};
_Enabled.prototype.onSearchDropdown.transitions = ['Disabled'];

View File

@@ -28,6 +28,7 @@ function Device(id, name, x, y, type, host_id) {
this.interfaces = [];
this.process_id_seq = util.natural_numbers(0);
this.processes = [];
this.in_group = false;
}
exports.Device = Device;
@@ -640,6 +641,7 @@ Group.prototype.update_membership = function (devices, groups) {
devices[i].y > y1 &&
devices[i].x < x2 &&
devices[i].y < y2) {
devices[i].in_group = true;
this.devices.push(devices[i]);
device_ids.push(devices[i].id);
}
@@ -918,6 +920,7 @@ function Animation(id, steps, data, scope, tracer, callback) {
this.frame_number_seq = util.natural_numbers(-1);
this.frame_number = 0;
this.data = data;
this.data.updateZoomBoolean = data.updateZoomBoolean !== undefined ? data.updateZoomBoolean : true;
this.callback = callback;
this.scope = scope;
this.interval = null;

View File

@@ -208,13 +208,10 @@ _Ready.prototype.onMouseDown = function (controller, msg_type, $event) {
if (last_selected.last_selected_device !== null) {
controller.changeState(Selected1);
controller.scope.onDetailsContextButton();
} else if (last_selected.last_selected_link !== null) {
controller.changeState(Selected1);
controller.scope.onDetailsContextButton();
} else if (last_selected.last_selected_interface !== null) {
controller.changeState(Selected1);
controller.scope.onDetailsContextButton();
} else {
controller.delegate_channel.send(msg_type, $event);
}
@@ -289,7 +286,7 @@ _Selected2.prototype.onMouseDown = function (controller, msg_type, $event) {
return;
}
}
controller.scope.first_channel.send('BindDocument', {});
controller.changeState(Ready);
controller.handle_message(msg_type, $event);
};
@@ -315,6 +312,9 @@ _Selected1.prototype.onMouseMove.transitions = ['Move'];
_Selected1.prototype.onMouseUp = function (controller) {
if(controller.scope.$parent.vm.rightPanelIsExpanded){
controller.scope.onDetailsContextButton();
}
controller.changeState(Selected2);
};
@@ -511,3 +511,10 @@ _ContextMenu.prototype.onMouseDown = function (controller) {
};
_ContextMenu.prototype.onMouseDown.transitions = ['Ready'];
_ContextMenu.prototype.onDetailsPanel = function (controller, msg_type, $event) {
controller.changeState(Selected2);
controller.handle_message(msg_type, $event);
};
_ContextMenu.prototype.onDetailsPanel.transitions = ['Selected2'];

View File

@@ -0,0 +1,29 @@
.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-noItems{
margin-top: 0px;
}
.Networking-form{
font-weight: normal;
}
.Networking-saveConfirmation{
font-weight: normal;
color: @default-succ;
text-align: right;
margin-top:15px;
}

View File

@@ -0,0 +1,92 @@
/*************************************************
* Copyright (c) 2016 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
export default
['$scope', '$state', '$stateParams', 'GenerateForm', 'ParseTypeChange', 'HostsService', '$rootScope',
function($scope, $state, $stateParams, GenerateForm, ParseTypeChange, HostsService, $rootScope){
$scope.parseType = 'yaml';
$scope.formCancel = function(){
$scope.$parent.$$childTail.closeDetailsPanel();
};
$scope.formSave = function(){
var host = {
id: $scope.item.id,
variables: $scope.variables === '---' || $scope.variables === '{}' ? null : $scope.variables,
name: $scope.item.name,
description: $scope.item.description,
enabled: $scope.item.enabled
};
HostsService.put(host).then(function(response){
$scope.saveConfirmed = true;
if(_.has(response, "data")){
$scope.$parent.$broadcast('hostUpdateSaved', response.data);
}
setTimeout(function(){
$scope.saveConfirmed = false;
}, 3000);
});
};
$scope.$parent.$on('showDetails', (e, data, canAdd) => {
if (!_.has(data, 'host_id')) {
$scope.item = data;
$scope.canAdd = canAdd;
} else {
$scope.item = data;
}
});
$scope.$watch('item', function(){
init();
});
var init = function(){
if($scope.item && $scope.item.host_id){
$scope.variables = getVars($scope.item.variables);
ParseTypeChange({
scope: $scope,
field_id: 'network_host_variables',
variable: 'variables',
});
}
};
// Adding this function b/c sometimes extra vars are returned to the
// UI as a string (ex: "foo: bar"), and other times as a
// json-object-string (ex: "{"foo": "bar"}"). CodeMirror wouldn't know
// how to prettify the latter. The latter occurs when host vars were
// system generated and not user-input (such as adding a cloud host);
function getVars(str){
// Quick function to test if the host vars are a json-object-string,
// by testing if they can be converted to a JSON object w/o error.
function IsJsonString(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
if(str === ''){
return '---';
}
else if(IsJsonString(str)){
str = JSON.parse(str);
return jsyaml.safeDump(str);
}
else if(!IsJsonString(str)){
return str;
}
}
// init();
}];

View File

@@ -0,0 +1,22 @@
/*************************************************
* Copyright (c) 2018 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import detailsController from './details.controller';
const templateUrl = require('~network-ui/network-details/details.partial.html');
export default [
function() {
return {
scope:{
item: "=",
canAdd: '@'
},
templateUrl,
controller: detailsController,
restrict: 'E',
};
}];

View File

@@ -0,0 +1,66 @@
<div class="Networking-panelHeader">
<div class="JobResults-panelHeaderText" translate="">
DETAILS <span ng-if="!item.host_id && item.name">| {{item.name}}</span>
</div>
</div>
<div class="List-noItems Networking-noItems" ng-if="!item.host_id">
{{item.type}} DETAILS NOT AVAILABLE
</div>
<div ng-show="item.host_id">
<form class="Form Networking-form ng-pristine ng-valid ng-valid-required" name="host_form" id="host_form" autocomplete="off" novalidate="">
<div class="form-group Form-formGroup Form-formGroup--fullWidth">
<label class="Form-inputLabelContainer" for="name">
<span class="Form-requiredAsterisk">*</span>
<span class="Form-inputLabel" translate="">Host Name</span><a id="awp-name" href="" aw-pop-over="<p>Provide a host name, ip address, or ip address:port. Examples include:</p><blockquote>myserver.domain.com<br/>127.0.0.1<br />10.1.0.140:25<br />server.example.com:25</blockquote>" data-placement="right" data-container="body" over-title="Host Name" class="help-link" data-original-title="" title="" tabindex="-1"><i class="fa fa-question-circle"></i></a>
</label>
<div>
<input type="text" ng-model="item.name" name="name" id="host_name" class="form-control Form-textInput Networking-input ng-pristine ng-untouched ng-valid ng-not-empty ng-valid-required" required="" ng-disabled="!(item.summary_fields.user_capabilities.edit || canAdd)">
<div class="error ng-hide" id="host-name-required-error" ng-show="host_form.name.$dirty &amp;&amp; host_form.name.$error.required">Please enter a value.</div>
<div class="error api-error ng-binding" id="host-name-api-error" ng-bind="name_api_error"></div>
</div>
</div>
<div class="form-group Form-formGroup Form-formGroup--fullWidth">
<label class="Form-inputLabelContainer" for="description">
<span class="Form-inputLabel" translate="">Description</span>
</label>
<div>
<input type="text" ng-model="item.description" name="description" id="host_description" class="form-control Form-textInput Networking-input" ng-disabled="!(item.summary_fields.user_capabilities.edit || canAdd)">
<div class="error api-error ng-binding" id="host-description-api-error" ng-bind="description_api_error"></div>
</div>
</div>
<div class="form-group Form-formGroup Form-formGroup--fullWidth">
<label class="Form-inputLabelContainer" for="variables">
<span class="Form-inputLabel" translate="">Variables</span>
<a id="awp-variables" href="" aw-pop-over="<p>Enter inventory variables using either JSON or YAML syntax. Use the radio button to toggle between the two.</p>JSON:<br />
<blockquote>{<br />&emsp;&quot;somevar&quot;: &quot;somevalue&quot;,<br />&emsp;&quot;password&quot;: &quot;magic&quot;<br /> }</blockquote>
YAML:<br />
<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>
<p>View JSON examples at <a href=&quot;http://www.json.org&quot; target=&quot;_blank&quot;>www.json.org</a></p><p>View YAML examples at <a href=&quot;http://docs.ansible.com/YAMLSyntax.html&quot; target=&quot;_blank&quot;>docs.ansible.com</a></p>"
data-placement="right" data-container="body" over-title="Host Variables" class="help-link" data-original-title="" title="" tabindex="-1">
<i class="fa fa-question-circle"></i>
</a>
<div class="FormToggle-container" id="host_variables_parse_type">
<div class="btn-group">
<label ng-class="{'btn-primary': parseType === 'yaml','Button-primary--hollow' : parseType === 'json'}" class="btn btn-xs btn-primary">
<input type="radio" value="yaml" ng-model="parseType" ng-change="parseTypeChange('parseType', 'variables')" class="ng-pristine ng-untouched ng-valid ng-not-empty">YAML
</label>
<label ng-class="{'btn-primary': parseType === 'json','Button-primary--hollow' : parseType === 'yaml'}" class="btn btn-xs Button-primary--hollow">
<input type="radio" value="json" ng-model="parseType" ng-change="parseTypeChange('parseType', 'variables')" class="ng-pristine ng-untouched ng-valid ng-not-empty">JSON
</label>
</div>
</div>
</label>
<textarea rows="6" ng-model="variables" name="variables" class="form-control Form-textArea Form-formGroup--fullWidth" id="network_host_variables"></textarea>
</div>
</form>
<div class="buttons Form-buttons" id="host_controls" ng-show="item.host_id">
<button type="button" class="btn btn-sm Form-cancelButton" id="host_cancel_btn" ng-show="(item.summary_fields.user_capabilities.edit || canAdd)" ng-click="formCancel()"> Cancel</button>
<button type="button" class="btn btn-sm Form-cancelButton ng-hide" id="host_close_btn" ng-show="!(item.summary_fields.user_capabilities.edit || canAdd)" ng-click="formCancel()"> Close</button>
<button type="button" class="btn btn-sm Form-saveButton" id="host_save_btn" ng-show="(item.summary_fields.user_capabilities.edit || canAdd)" ng-click="formSave()" ng-disabled="host_form.$invalid || host_form.$pending"> Save</button>
</div>
<div class="Networking-saveConfirmation" ng-show="saveConfirmed">
Save Complete <i class="fa fa-check-circle"></i>
</div>
</div>

View File

@@ -0,0 +1,11 @@
/*************************************************
* Copyright (c) 2018 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import awxNetDetailsPanel from './details.directive';
export default
angular.module('networkDetailsDirective', [])
.directive('awxNetDetailsPanel', awxNetDetailsPanel);

View File

@@ -87,38 +87,6 @@
right:0px;
}
.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-resultRowLabel{
width: initial;
}
.Networking-resultRow--variables {
flex-direction: column;
#cm-variables-container {
width: 100%;
}
}
.Networking-noItems{
margin-top: 0px;
}
.Networking-toolbar{
min-height: 40px;
width:100%;
@@ -139,22 +107,18 @@
.Networking-breadCrumbText{
color:@default-link;
text-transform: uppercase;
font-size: 14px;
}
.Networking-toolbarLeftSide--expanded{
width: calc(~"100% - 201px");
// margin-left:201px;
left:201px;
.Networking-breadCrumbSlash{
padding: 0px 10px 0px 10px;
color: #707070;
}
.Networking-toolbarBothPanels--expanded{
width: calc(~"100% - 601px");
// margin-right:400px;
left:201px;
}
.Networking-toolbarRightSide--expanded{
width: calc(~"100% - 445px");
.Networking-breadCrumbText--last{
color: #707070;
text-transform: none;
}
.Networking-toolbarButton{

View File

@@ -15,7 +15,6 @@ function NetworkingController (models, $state, $scope, strings, CreateSelect2) {
vm.jumpToPanelExpanded = false;
vm.keyPanelExpanded = false;
$scope.devices = [];
// $scope.device = null;
vm.close = () => {
$state.go('inventories');
};
@@ -44,23 +43,6 @@ function NetworkingController (models, $state, $scope, strings, CreateSelect2) {
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];
@@ -68,7 +50,8 @@ function NetworkingController (models, $state, $scope, strings, CreateSelect2) {
value: device.id,
text: device.name,
label: device.name,
id: device.id
id: device.id,
type: device.type
});
}
@@ -106,12 +89,12 @@ function NetworkingController (models, $state, $scope, strings, CreateSelect2) {
});
$('#networking-search').on('select2:select', (e) => {
$scope.$broadcast('search', e.params.data);
$scope.$broadcast('search', $scope.device);
});
$('#networking-search').on('select2:open', () => {
$('.select2-dropdown').addClass('Networking-dropDown');
$scope.$broadcast('unbind');
$scope.$broadcast('SearchDropdown');
});
$('#networking-search').on('select2:close', () => {
@@ -119,7 +102,7 @@ function NetworkingController (models, $state, $scope, strings, CreateSelect2) {
$('.select2-container-active').removeClass('select2-container-active');
$(':focus').blur();
}, 1);
$scope.$broadcast('bind');
$scope.$broadcast('SearchDropdownClose');
});
}

View File

@@ -23,12 +23,12 @@
</div>
<div class="Networking-toolbarRightSide">
<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 id="networking-search"
ng-model="device"
ng-options="device.label group by device.type | capitalize for device in devices | orderBy:'label' "
style="width:100%">
<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}">
@@ -117,77 +117,23 @@
</div>
</div>
<div class="Networking-toolbar Networking-breadCrumbBar">
<div class="Networking-breadCrumbText"></div>
<div class="Networking-breadCrumbText">Foo </div><div class="Networking-breadCrumbSlash">/</div>
<div class="Networking-breadCrumbText">Bar </div><div class="Networking-breadCrumbSlash">/</div>
<div class="Networking-breadCrumbText">Bread </div><div class="Networking-breadCrumbSlash">/</div>
<div class="Networking-breadCrumbText Networking-breadCrumbText--last">crumb</div>
</div>
</div>
</div>
<div class="Networking-detailPanel" ng-show="vm.rightPanelIsExpanded">
<!--beginning of header-->
<div class="Networking-panelHeader">
<div class="JobResults-panelHeaderText" translate="">
DETAILS <span ng-if="!item.host_id && item.name">| {{item.name}}</span>
</div>
</div>
<!--end of header-->
<!--beginning of name row -->
<div class="JobResults-resultRow" ng-if="item.host_id">
<label class="JobResults-resultRowLabel Networking-resultRowLabel" translate="">
Name
</label>
<div class="JobResults-resultRowText">
{{item.name}}
</div>
</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>
<!-- beginning of extra variable row -->
<div class="JobResults-resultRow JobResults-resultRow--variables" ng-show="item.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="item.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>
<awx-net-details-panel item="item"></awx-net-details-panel>
</div>
<div class="Networking-canvasPanel">
<awx-network-ui></awx-network-ui>
</div>
<div class="Networking-zoomPanel" ng-class="{'Networking-zoomPanel--expanded' : vm.rightPanelIsExpanded}">
<awx-net-zoom-widget></awx-net-zoom-widget>
</div>
<div id="alert-modal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">

View File

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

View File

@@ -21,11 +21,12 @@ 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('./svg-crowbar.js');
var ReconnectingWebSocket = require('reconnectingwebsocket');
var NetworkUIController = function($scope, $document, $location, $window, $http,
$q, $state, ProcessErrors, ConfigService) {
$q, $state, ProcessErrors, ConfigService, rbacUiControlService) {
window.scope = $scope;
var i = 0;
@@ -185,6 +186,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$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);
$scope.details_panel_controller = new fsm.FSMController($scope, "details_panel_fsm", details_panel_fsm.Start, $scope);
$scope.link_controller = new fsm.FSMController($scope, "link_fsm", link.Start, $scope);
$scope.stream_controller = new fsm.FSMController($scope, "stream_fsm", stream_fsm.Start, $scope);
$scope.group_controller = new fsm.FSMController($scope, "group_fsm", group.Start, $scope);
@@ -318,8 +320,11 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.move_controller.delegate_channel = new fsm.Channel($scope.move_controller,
$scope.device_detail_controller,
$scope);
$scope.details_panel_controller.delegate_channel = new fsm.Channel($scope.details_panel_controller,
$scope.move_controller,
$scope);
$scope.link_controller.delegate_channel = new fsm.Channel($scope.link_controller,
$scope.move_controller,
$scope.details_panel_controller,
$scope);
$scope.stream_controller.delegate_channel = new fsm.Channel($scope.stream_controller,
$scope.link_controller,
@@ -625,6 +630,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
// Conext Menu Button Handlers
$scope.removeContextMenu = function(){
$scope.move_controller.handle_message("Ready", {});
let context_menu = $scope.context_menus[0];
context_menu.enabled = false;
context_menu.x = -100000;
@@ -637,61 +643,72 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
};
$scope.closeDetailsPanel = function () {
$scope.$emit('closeDetailsPanel');
$scope.first_channel.send('DetailsPanelClose', {});
};
$scope.onDetailsContextButton = function (panelBoolean) {
if (!$scope.disconnected) {
$scope.$on('hostUpdateSaved', (e, host) => {
if (host.variables !== "" && $scope.selected_devices.length === 1) {
host.data = jsyaml.safeLoad(host.variables);
$scope.selected_devices[0].type = host.data.type;
}
});
$scope.onDetailsContextButton = function () {
function emitCallback(item, canAdd){
$scope.first_channel.send('DetailsPanel', {});
$scope.removeContextMenu();
// show details for devices
if ($scope.selected_devices.length === 1){
$scope.update_toolbox_heights();
$scope.$emit('showDetails', item, canAdd);
}
// following block is intended for devices added in the network UI but not in Tower
if ($scope.selected_devices[0].host_id === 0){
let host = $scope.selected_devices[0];
$scope.update_toolbox_heights();
$scope.$emit('showDetails', host, panelBoolean !== null ? panelBoolean: true);
}
// 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[0].host_id !== 0){
let host_id = $scope.selected_devices[0].host_id;
let url = `/api/v2/hosts/${host_id}/`;
$http.get(url)
.then(function(response) {
let host = response.data;
host.host_id = host.id;
$scope.update_toolbox_heights();
$scope.$emit('showDetails', host, panelBoolean !== null ? panelBoolean: true);
// 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);
});
}
})
.catch(({data, status}) => {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get host data: ' + status });
});
}
}
// show details for interfaces
else if($scope.selected_interfaces.length === 1){
emitCallback($scope.selected_interfaces[0]);
}
// show details for interfaces
else if($scope.selected_interfaces.length === 1){
let selected_interface = $scope.selected_interfaces[0];
$scope.update_toolbox_heights();
$scope.$emit('showDetails', selected_interface, panelBoolean !== null ? panelBoolean: true);
}
// show details for links
else if($scope.selected_links.length === 1){
emitCallback($scope.selected_links[0]);
}
// show details for links
else if($scope.selected_links.length === 1){
let link = $scope.selected_links[0];
$scope.update_toolbox_heights();
$scope.$emit('showDetails', link, panelBoolean !== null ? panelBoolean: true);
}
//show details for groups, racks, and sites
else if ($scope.selected_groups.length === 1){
emitCallback($scope.selected_groups[0]);
}
//show details for groups, racks, and sites
else if ($scope.selected_groups.length === 1){
let group = $scope.selected_groups[0];
$scope.update_toolbox_heights();
$scope.$emit('showDetails', group, panelBoolean !== null ? panelBoolean: true);
}
}
};
$scope.onRenameContextButton = function (button) {
@@ -830,15 +847,30 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope[`on${functionName}Button`]();
});
$scope.$on('unbind', function(){
$scope.first_channel.send('UnbindDocument', {});
$scope.$on('SearchDropdown', function(){
$scope.first_channel.send('SearchDropdown', {});
});
$scope.$on('bind', function(){
$scope.first_channel.send('BindDocument', {});
$scope.$on('SearchDropdownClose', function(){
$scope.first_channel.send('SearchDropdownClose', {});
});
$scope.jump_to_animation = function(jump_to_x, jump_to_y, jump_to_scale) {
$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.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);
//console.log({v_center: v_center});
@@ -857,7 +889,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
distance: distance,
end_height: (1.0/jump_to_scale) - 1,
current_scale: $scope.current_scale,
scope: $scope
scope: $scope,
updateZoomBoolean: updateZoom
},
$scope,
$scope,
@@ -878,21 +911,6 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$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){
@@ -911,6 +929,12 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
}
});
$scope.$on('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) / 40)
$scope.jump_to_animation(v_center.x, v_center.y, scale, false);
});
$scope.onDeployButton = function (button) {
$scope.send_control_message(new messages.Deploy($scope.client_id));
};
@@ -1488,6 +1512,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$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.group_id_seq = util.natural_numbers(data.group_id_seq);
$scope.device_id_seq = util.natural_numbers(data.device_id_seq);
@@ -1755,6 +1780,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
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();
}
@@ -1982,6 +2008,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.device_detail_controller.state.start($scope.device_detail_controller);
$scope.move_controller.state = move.Start;
$scope.move_controller.state.start($scope.move_controller);
$scope.details_panel_controller.state = details_panel_fsm.Start;
$scope.details_panel_controller.state.start($scope.details_panel_controller);
$scope.link_controller.state = link.Start;
$scope.link_controller.state.start($scope.link_controller);
$scope.stream_controller.state = stream_fsm.Start;

View File

@@ -44,7 +44,7 @@
<g awx-net-stream></g>
</g> <!-- end ng-repeat stream in streams-->
</g> <!-- end ng-if current_scale -->
<g ng-if="current_scale > 0.5 && current_scale < 5">
<g>
<g ng-repeat="item in devices"
ng-attr-transform="translate({{item.x}},{{item.y}})"

View File

@@ -194,6 +194,9 @@ _Ready.prototype.onPasteRack = function (controller, msg_type, message) {
_Selected1.prototype.onMouseUp = function (controller) {
if(controller.scope.$parent.vm.rightPanelIsExpanded){
controller.scope.onDetailsContextButton();
}
controller.changeState(Selected2);
};
@@ -418,7 +421,6 @@ _Ready.prototype.onMouseDown = function (controller, msg_type, $event) {
if (selected) {
controller.changeState(Selected1);
controller.scope.onDetailsContextButton();
} else {
controller.delegate_channel.send(msg_type, $event);
}

View File

@@ -1,81 +1,83 @@
<!-- Copyright (c) 2017 Red Hat, Inc. -->
<g transform="scale(0.75)">
<g ng-if="item.moving">
<!--horizontal line -->
<line x1="-150"
y1="0"
x2="150"
y2="0"
class="NetworkUI--construction">
</line>
<!-- end horizontal line -->
<g ng-if="item.icon || (current_scale > 0.5 && current_scale < 5) || !item.in_group">
<g transform="scale(0.75)">
<g ng-if="item.moving">
<!--horizontal line -->
<line x1="-150"
y1="0"
x2="150"
y2="0"
class="NetworkUI--construction">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-150"
x2="0"
y2="150"
class="NetworkUI--construction">
</line>
<!-- end vertical line -->
</g>
<!-- vertical line -->
<line x1="0"
y1="-150"
x2="0"
y2="150"
class="NetworkUI--construction">
</line>
<!-- end vertical line -->
</g>
<g ng-if="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<g ng-if="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-60"
x2="0"
y2="60"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- vertical line -->
<line x1="0"
y1="-60"
x2="0"
y2="60"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- debug rectangle -->
<rect x="-50"
y="-50"
width="100"
height="100"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<g transform="translate(-50,-50)">
<circle
cx="50"
cy="50"
r="50"
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__router--selected-conflict' : item.selected ? 'NetworkUI__router--selected' : 'NetworkUI__router--remote-selected' : 'NetworkUI__router--background'}}">
</circle>
<g transform="scale(2)">
<path
class="NetworkUI__router"
d="M42.7,7.3c-9.8-9.8-25.6-9.8-35.4,0c-9.8,9.8-9.8,25.6,0,35.4c9.8,9.8,25.6,9.8,35.4,0
C52.4,32.9,52.4,17.1,42.7,7.3z M20,12.3l4.2-4.2c0.2-0.2,0.5-0.3,0.8-0.3c0.3,0,0.6,0.1,0.8,0.3l4.2,4.2c0.4,0.4,0.4,1.2,0,1.6
c-0.4,0.4-1.2,0.4-1.6,0l-2.3-2.3v10c0,0.6-0.5,1.1-1.1,1.1c-0.6,0-1.1-0.5-1.1-1.1l0-10L21.6,14c-0.4,0.4-1.2,0.4-1.6,0
C19.5,13.5,19.5,12.8,20,12.3z M15.6,29.8c-0.4-0.4-0.4-1.2,0-1.6l0,0l2.1-2.1l-8.7,0c-0.6,0-1.1-0.5-1.1-1.1c0-0.3,0.1-0.6,0.3-0.8
C8.4,24,8.7,23.8,9,23.8l8.7,0l-2.1-2.1c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.2-0.4,1.6,0l4,4c0.2,0.2,0.3,0.5,0.3,0.8
c0,0.3-0.1,0.6-0.3,0.8l0,0l-4,4C16.8,30.3,16.1,30.3,15.6,29.8z M30,37.7l-4.2,4.2c-0.2,0.2-0.5,0.3-0.8,0.3
c-0.3,0-0.6-0.1-0.8-0.3L20,37.7c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.2-0.4,1.6,0l2.3,2.3l0-10.2c0-0.3,0.1-0.6,0.3-0.8
c0.2-0.2,0.5-0.3,0.8-0.3c0.6,0,1.1,0.5,1.1,1.1l0,10.2l2.3-2.3c0.4-0.4,1.2-0.4,1.6,0C30.5,36.5,30.5,37.2,30,37.7z M41,26.2
l-8.9,0l2.1,2.1c0.4,0.4,0.5,1.2,0,1.6c-0.4,0.4-1.2,0.4-1.6,0l-4-4c-0.2-0.2-0.3-0.5-0.3-0.8c0-0.3,0.1-0.6,0.3-0.8l0,0l4-4
c0.4-0.4,1.2-0.4,1.6,0c0.4,0.4,0.4,1.2,0,1.6l0,0l-2.1,2.1l8.8,0c0.6,0,1.1,0.5,1.1,1.1C42.1,25.6,41.6,26.2,41,26.2z"/>
<!-- debug rectangle -->
<rect x="-50"
y="-50"
width="100"
height="100"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<g transform="translate(-50,-50)">
<circle
cx="50"
cy="50"
r="50"
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__router--selected-conflict' : item.selected ? 'NetworkUI__router--selected' : 'NetworkUI__router--remote-selected' : 'NetworkUI__router--background'}}">
</circle>
<g transform="scale(2)">
<path
class="NetworkUI__router"
d="M42.7,7.3c-9.8-9.8-25.6-9.8-35.4,0c-9.8,9.8-9.8,25.6,0,35.4c9.8,9.8,25.6,9.8,35.4,0
C52.4,32.9,52.4,17.1,42.7,7.3z M20,12.3l4.2-4.2c0.2-0.2,0.5-0.3,0.8-0.3c0.3,0,0.6,0.1,0.8,0.3l4.2,4.2c0.4,0.4,0.4,1.2,0,1.6
c-0.4,0.4-1.2,0.4-1.6,0l-2.3-2.3v10c0,0.6-0.5,1.1-1.1,1.1c-0.6,0-1.1-0.5-1.1-1.1l0-10L21.6,14c-0.4,0.4-1.2,0.4-1.6,0
C19.5,13.5,19.5,12.8,20,12.3z M15.6,29.8c-0.4-0.4-0.4-1.2,0-1.6l0,0l2.1-2.1l-8.7,0c-0.6,0-1.1-0.5-1.1-1.1c0-0.3,0.1-0.6,0.3-0.8
C8.4,24,8.7,23.8,9,23.8l8.7,0l-2.1-2.1c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.2-0.4,1.6,0l4,4c0.2,0.2,0.3,0.5,0.3,0.8
c0,0.3-0.1,0.6-0.3,0.8l0,0l-4,4C16.8,30.3,16.1,30.3,15.6,29.8z M30,37.7l-4.2,4.2c-0.2,0.2-0.5,0.3-0.8,0.3
c-0.3,0-0.6-0.1-0.8-0.3L20,37.7c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.2-0.4,1.6,0l2.3,2.3l0-10.2c0-0.3,0.1-0.6,0.3-0.8
c0.2-0.2,0.5-0.3,0.8-0.3c0.6,0,1.1,0.5,1.1,1.1l0,10.2l2.3-2.3c0.4-0.4,1.2-0.4,1.6,0C30.5,36.5,30.5,37.2,30,37.7z M41,26.2
l-8.9,0l2.1,2.1c0.4,0.4,0.5,1.2,0,1.6c-0.4,0.4-1.2,0.4-1.6,0l-4-4c-0.2-0.2-0.3-0.5-0.3-0.8c0-0.3,0.1-0.6,0.3-0.8l0,0l4-4
c0.4-0.4,1.2-0.4,1.6,0c0.4,0.4,0.4,1.2,0,1.6l0,0l-2.1,2.1l8.8,0c0.6,0,1.1,0.5,1.1,1.1C42.1,25.6,41.6,26.2,41,26.2z"/>
</g>
</g>
<g ng-show="item.icon || current_scale > 0.5">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__router-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#background)"
text-anchor="middle"
x="0"
y="70"> {{item.name}}</text>
<text class="NetworkUI__router-text" filter="url(#background)" text-anchor="middle" x="0" y="70">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
</g>
<g ng-show="item.icon || current_scale > 0.5">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__router-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#background)"
text-anchor="middle"
x="0"
y="70"> {{item.name}}</text>
<text class="NetworkUI__router-text" filter="url(#background)" text-anchor="middle" x="0" y="70">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
</g>

View File

@@ -245,6 +245,9 @@ _Ready.prototype.onPasteSite = function (controller, msg_type, message) {
_Selected1.prototype.onMouseUp = function (controller) {
if(controller.scope.$parent.vm.rightPanelIsExpanded){
controller.scope.onDetailsContextButton();
}
controller.changeState(Selected2);
};
@@ -506,7 +509,6 @@ _Ready.prototype.onMouseDown = function (controller, msg_type, $event) {
if (selected) {
controller.changeState(Selected1);
controller.scope.onDetailsContextButton();
} else {
controller.delegate_channel.send(msg_type, $event);
}

View File

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

View File

@@ -1,83 +1,85 @@
<!-- Copyright (c) 2017 Red Hat, Inc. -->
<g transform="scale(0.75)">
<g ng-if="item.moving">
<!--horizontal line -->
<line x1="-150"
y1="0"
x2="150"
y2="0"
class="NetworkUI--construction">
</line>
<!-- end horizontal line -->
<g ng-if="item.icon || (current_scale > 0.5 && current_scale < 5) || !item.in_group">
<g transform="scale(0.75)">
<g ng-if="item.moving">
<!--horizontal line -->
<line x1="-150"
y1="0"
x2="150"
y2="0"
class="NetworkUI--construction">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-150"
x2="0"
y2="150"
class="NetworkUI--construction">
</line>
<!-- end vertical line -->
</g>
<!-- vertical line -->
<line x1="0"
y1="-150"
x2="0"
y2="150"
class="NetworkUI--construction">
</line>
<!-- end vertical line -->
</g>
<g ng-if="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<g ng-if="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-60"
x2="0"
y2="60"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- vertical line -->
<line x1="0"
y1="-60"
x2="0"
y2="60"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- debug rectangle -->
<rect x="-50"
y="-50"
width="100"
height="100"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<!-- debug rectangle -->
<rect x="-50"
y="-50"
width="100"
height="100"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<g transform="translate(-50,-50)">
<rect
ry=20
rx=20
width=100
height=100
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__switch--selected-conflict' : item.selected ? 'NetworkUI__switch--selected' : 'NetworkUI__switch--remote-selected' : 'NetworkUI__switch--background'}}">
</rect>
<g transform="scale(2)">
<path
class="NetworkUI__switch"
d="M40.8,0H9.2C4.2,0,0,4.2,0,9.2v31.5C0,45.8,4.2,50,9.2,50h31.5c5.1,0,9.2-4.2,9.2-9.2V9.2C50,4.2,45.8,0,40.8,0
z M22.2,12.6l11.1,0l-2.3-2.3c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.2-0.4,1.6,0l4.2,4.2c0.2,0.2,0.3,0.5,0.3,0.8c0,0.3-0.1,0.6-0.3,0.8
l-4.2,4.2c-0.4,0.4-1.2,0.4-1.6,0c-0.4-0.4-0.4-1.2,0-1.6l2.3-2.3H22.2c-0.6,0-1.1-0.5-1.1-1.1C21.1,13.1,21.6,12.6,22.2,12.6z
M10,21.2c0-0.3,0.1-0.6,0.3-0.8l4.2-4.2c0.4-0.4,1.2-0.4,1.6,0c0.4,0.4,0.4,1.2,0,1.6l-2.3,2.3H25c0.6,0,1.1,0.5,1.1,1.1
c0,0.6-0.5,1.1-1.1,1.1l-11.1,0l2.3,2.3c0.4,0.4,0.4,1.2,0,1.6c-0.4,0.4-1.2,0.4-1.6,0L10.3,22C10.1,21.8,10,21.5,10,21.2z
M27.8,37.4l-11.1,0l2.3,2.3c0.4,0.4,0.4,1.2,0,1.6c-0.4,0.4-1.2,0.4-1.6,0l-4.2-4.2c-0.2-0.2-0.3-0.5-0.3-0.8
c0-0.3,0.1-0.6,0.3-0.8l4.2-4.2c0.4-0.4,1.2-0.4,1.6,0c0.4,0.4,0.4,1.2,0,1.6l-2.3,2.3h11.1c0.6,0,1.1,0.5,1.1,1.1
C28.9,36.9,28.4,37.4,27.8,37.4z M39.7,29.6l-4.2,4.2c-0.4,0.4-1.2,0.4-1.6,0c-0.4-0.4-0.4-1.2,0-1.6l2.3-2.3H25
c-0.6,0-1.1-0.5-1.1-1.1c0-0.6,0.5-1.1,1.1-1.1l11.1,0l-2.3-2.3c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.2-0.4,1.6,0l4.2,4.2
c0.2,0.2,0.3,0.5,0.3,0.8C40,29.1,39.9,29.4,39.7,29.6z"/>
<g transform="translate(-50,-50)">
<rect
ry=20
rx=20
width=100
height=100
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__switch--selected-conflict' : item.selected ? 'NetworkUI__switch--selected' : 'NetworkUI__switch--remote-selected' : 'NetworkUI__switch--background'}}">
</rect>
<g transform="scale(2)">
<path
class="NetworkUI__switch"
d="M40.8,0H9.2C4.2,0,0,4.2,0,9.2v31.5C0,45.8,4.2,50,9.2,50h31.5c5.1,0,9.2-4.2,9.2-9.2V9.2C50,4.2,45.8,0,40.8,0
z M22.2,12.6l11.1,0l-2.3-2.3c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.2-0.4,1.6,0l4.2,4.2c0.2,0.2,0.3,0.5,0.3,0.8c0,0.3-0.1,0.6-0.3,0.8
l-4.2,4.2c-0.4,0.4-1.2,0.4-1.6,0c-0.4-0.4-0.4-1.2,0-1.6l2.3-2.3H22.2c-0.6,0-1.1-0.5-1.1-1.1C21.1,13.1,21.6,12.6,22.2,12.6z
M10,21.2c0-0.3,0.1-0.6,0.3-0.8l4.2-4.2c0.4-0.4,1.2-0.4,1.6,0c0.4,0.4,0.4,1.2,0,1.6l-2.3,2.3H25c0.6,0,1.1,0.5,1.1,1.1
c0,0.6-0.5,1.1-1.1,1.1l-11.1,0l2.3,2.3c0.4,0.4,0.4,1.2,0,1.6c-0.4,0.4-1.2,0.4-1.6,0L10.3,22C10.1,21.8,10,21.5,10,21.2z
M27.8,37.4l-11.1,0l2.3,2.3c0.4,0.4,0.4,1.2,0,1.6c-0.4,0.4-1.2,0.4-1.6,0l-4.2-4.2c-0.2-0.2-0.3-0.5-0.3-0.8
c0-0.3,0.1-0.6,0.3-0.8l4.2-4.2c0.4-0.4,1.2-0.4,1.6,0c0.4,0.4,0.4,1.2,0,1.6l-2.3,2.3h11.1c0.6,0,1.1,0.5,1.1,1.1
C28.9,36.9,28.4,37.4,27.8,37.4z M39.7,29.6l-4.2,4.2c-0.4,0.4-1.2,0.4-1.6,0c-0.4-0.4-0.4-1.2,0-1.6l2.3-2.3H25
c-0.6,0-1.1-0.5-1.1-1.1c0-0.6,0.5-1.1,1.1-1.1l11.1,0l-2.3-2.3c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.2-0.4,1.6,0l4.2,4.2
c0.2,0.2,0.3,0.5,0.3,0.8C40,29.1,39.9,29.4,39.7,29.6z"/>
</g>
</g>
<g>
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__switch-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#background)"
text-anchor="middle"
x="0"
y="70"> {{item.name}}</text>
<text class="NetworkUI__switch-text" filter="url(#background)" text-anchor="middle" x="0" y="70">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
</g>
<g ng-show="item.icon || current_scale > 0.5">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__switch-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#background)"
text-anchor="middle"
x="0"
y="70"> {{item.name}}</text>
<text class="NetworkUI__switch-text" filter="url(#background)" text-anchor="middle" x="0" y="70">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
<g>
</g>

View File

@@ -82,6 +82,7 @@ _Scale.prototype.onMouseWheel = function (controller, msg_type, message) {
controller.scope.panY = new_panY;
var item = controller.scope.context_menus[0];
item.enabled = false;
controller.scope.$emit('awxNet-UpdateZoomWidget', controller.scope.current_scale, true);
controller.scope.updatePanAndScale();
controller.changeState(Ready);
};

View File

@@ -0,0 +1,11 @@
/*************************************************
* Copyright (c) 2018 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
import awxNetZoomWidget from './zoom.directive';
export default
angular.module('networkZoomWidget', [])
.directive('awxNetZoomWidget', awxNetZoomWidget);

View File

@@ -0,0 +1,59 @@
.Networking-zoomPanel{
position: absolute;
bottom:0px;
right:0px;
border-top: 1px solid #B7B7B7;
border-left: 1px solid #B7B7B7;
width: 200px;
height:60px;
}
.Networking-zoomPanel--expanded{
right:400px;
}
.NetworkingControls-manualControls{
position: absolute;
background-color: #FFFFFF;
padding-left:15px;
width: 100%;
}
.NetworkingControls-Zoom{
display: flex;
flex: 1 0 auto;
}
.NetworkingControls-Zoom--button {
line-height: 60px;
color: @default-icon;
}
.NetworkingControls-Zoom--button:hover {
color: @default-link-hov;
}
.NetworkingControls-zoomSlider {
width: 150px;
padding-left: 8px;
padding-right: 8px;
}
.NetworkingControls-zoomPercentage {
text-align: center;
font-size: 0.7em;
height: 24px;
line-height: 24px;
}
.ui-slider-handle.ui-state-default.ui-corner-all {
border-radius: 50%;
border-color: @default-link;
background: @default-link;
}
.ui-slider-handle.ui-state-default.ui-corner-all:hover,
.ui-slider-handle.ui-state-default.ui-corner-all:active {
border-color: @default-link-hov;
background: @default-link-hov;
}

View File

@@ -0,0 +1,60 @@
/*************************************************
* Copyright (c) 2018 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
// import detailsController from './details.controller';
const templateUrl = require('~network-ui/zoom-widget/zoom.partial.html');
export default [
function() {
return {
templateUrl,
restrict: 'E',
link(scope){
function init() {
scope.zoom = 100;
$( "#networking-slider" ).slider({
value:100,
min: 0,
max: 200,
step: 10,
slide: function( event, ui ) {
scope.zoom = ui.value;
scope.zoomTo();
}
});
}
init();
scope.$parent.$on('awxNet-UpdateZoomWidget', (e, scale, updateBoolean) => {
if(scale && updateBoolean){
// scale is included, meaning this was triggered by
// the view FSM's onMouseWheel transition
let sliderPercent = 40 * (Math.log10(scale) + 3);
scope.zoom = Math.round(sliderPercent / 10) * 10;
}
$("#networking-slider").slider('value', scope.zoom);
});
scope.zoomTo = function() {
scope.zoom = Math.ceil(scope.zoom / 10) * 10;
this.$parent.$broadcast('zoom', scope.zoom);
};
scope.zoomOut = function(){
scope.zoom = scope.zoom - 10 > 0 ? scope.zoom - 10 : 0;
this.$parent.$broadcast('zoom', scope.zoom);
};
scope.zoomIn = function(){
scope.zoom = scope.zoom + 10 < 200 ? scope.zoom + 10 : 200;
this.$parent.$broadcast('zoom', scope.zoom);
};
}
};
}];

View File

@@ -0,0 +1,14 @@
<div class="NetworkingControls-manualControls">
<div class="NetworkingControls-Zoom">
<div class="NetworkingControls-Zoom--button NetworkingControls-Zoom--minus" ng-click="zoomOut()">
<i class="fa fa-minus" aria-hidden="true"></i>
</div>
<div class="NetworkingControls-zoomSlider">
<div class="NetworkingControls-zoomPercentage">{{zoom}}%</div>
<div id="networking-slider"></div>
</div>
<div class="NetworkingControls-Zoom--button NetworkingControls-Zoom--plus" ng-click="zoomIn()">
<i class="fa fa-plus" aria-hidden="true"></i>
</div>
</div>
</div>