mirror of
https://github.com/ansible/awx.git
synced 2026-02-26 23:46:05 -03:30
Merge pull request #1402 from jaredevantabor/vars-component
Adds atCodeMirror directive
This commit is contained in:
@@ -352,12 +352,8 @@
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.JobResults-resultRow--variables {
|
.JobResults-codeMirrorResultRowLabel{
|
||||||
flex-direction: column;
|
font-size: 12px;
|
||||||
|
|
||||||
#cm-variables-container {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.JobResults-resultRowLabel {
|
.JobResults-resultRowLabel {
|
||||||
|
|||||||
@@ -398,8 +398,9 @@ function getExtraVarsDetails () {
|
|||||||
const label = 'Extra Variables';
|
const label = 'Extra Variables';
|
||||||
const tooltip = 'Read-only view of extra variables added to the job template.';
|
const tooltip = 'Read-only view of extra variables added to the job template.';
|
||||||
const value = parse(extraVars);
|
const value = parse(extraVars);
|
||||||
|
const disabled = true;
|
||||||
|
|
||||||
return { label, tooltip, value };
|
return { label, tooltip, value, disabled };
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLabelDetails () {
|
function getLabelDetails () {
|
||||||
@@ -558,21 +559,6 @@ function AtJobDetailsController (
|
|||||||
vm.job = _.get(resource.model, 'model.GET', {});
|
vm.job = _.get(resource.model, 'model.GET', {});
|
||||||
vm.canDelete = resource.model.get('summary_fields.user_capabilities.delete');
|
vm.canDelete = resource.model.get('summary_fields.user_capabilities.delete');
|
||||||
|
|
||||||
// XX - Codemirror
|
|
||||||
if (vm.extraVars) {
|
|
||||||
const cm = {
|
|
||||||
parseType: 'yaml',
|
|
||||||
$apply: $scope.$apply,
|
|
||||||
variables: vm.extraVars.value,
|
|
||||||
};
|
|
||||||
|
|
||||||
ParseTypeChange({
|
|
||||||
field_id: 'cm-extra-vars',
|
|
||||||
readOnly: true,
|
|
||||||
scope: cm,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.cancelJob = cancelJob;
|
vm.cancelJob = cancelJob;
|
||||||
vm.deleteJob = deleteJob;
|
vm.deleteJob = deleteJob;
|
||||||
vm.toggleLabels = toggleLabels;
|
vm.toggleLabels = toggleLabels;
|
||||||
|
|||||||
@@ -252,23 +252,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- EXTRA VARIABLES DETAIL -->
|
<!-- EXTRA VARIABLES DETAIL -->
|
||||||
<div class="JobResults-resultRow JobResults-resultRow--variables" ng-show="vm.extraVars">
|
<at-code-mirror
|
||||||
<label class="JobResults-resultRowLabel JobResults-resultRowLabel--fullWidth">
|
ng-if="vm.extraVars"
|
||||||
<span>{{ vm.extraVars.label }}</span>
|
variables="{{ vm.extraVars.value }}"
|
||||||
<i class="JobResults-extraVarsHelp fa fa-question-circle"
|
tooltip="{{ vm.extraVars.tooltip }}"
|
||||||
aw-tool-tip="{{ vm.extraVars.tooltip }}"
|
label="{{ vm.extraVars.label}}"
|
||||||
data-placement="top">
|
label-class="JobResults-codeMirrorResultRowLabel"
|
||||||
</i>
|
disabled="{{ vm.extraVars.disabled }}">
|
||||||
</label>
|
</at-code-mirror>
|
||||||
<textarea
|
|
||||||
disabled="disabled"
|
|
||||||
rows="6"
|
|
||||||
ng-model="vm.extraVars.value"
|
|
||||||
name="variables"
|
|
||||||
class="form-control Form-textArea Form-textAreaLabel Form-formGroup--fullWidth"
|
|
||||||
id="cm-extra-vars">
|
|
||||||
</textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- LABELS DETAIL -->
|
<!-- LABELS DETAIL -->
|
||||||
<div class="JobResults-resultRow" ng-show="vm.labels">
|
<div class="JobResults-resultRow" ng-show="vm.labels">
|
||||||
|
|||||||
@@ -10,3 +10,4 @@
|
|||||||
@import 'tabs/_index';
|
@import 'tabs/_index';
|
||||||
@import 'truncate/_index';
|
@import 'truncate/_index';
|
||||||
@import 'utility/_index';
|
@import 'utility/_index';
|
||||||
|
@import 'code-mirror/_index';
|
||||||
|
|||||||
76
awx/ui/client/lib/components/code-mirror/_index.less
Normal file
76
awx/ui/client/lib/components/code-mirror/_index.less
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
.noselect {
|
||||||
|
-webkit-touch-callout: none; /* iOS Safari */
|
||||||
|
-webkit-user-select: none; /* Chrome/Safari/Opera */
|
||||||
|
-khtml-user-select: none; /* Konqueror */
|
||||||
|
-moz-user-select: none; /* Firefox */
|
||||||
|
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||||
|
user-select: none; /* Non-prefixed version, currently
|
||||||
|
not supported by any browser */
|
||||||
|
}
|
||||||
|
|
||||||
|
.atCodeMirror-label{
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atCodeMirror-labelLeftSide{
|
||||||
|
flex: 1 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atCodeMirror-labelText{
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #707070;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: small;
|
||||||
|
padding-right: 5px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atCodeMirror-toggleContainer{
|
||||||
|
margin: 0 0 0 10px;
|
||||||
|
display: initial;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.atCodeMirror-expandTextContainer{
|
||||||
|
flex: 1 0 auto;
|
||||||
|
text-align: right;
|
||||||
|
font-weight: normal;
|
||||||
|
color: @default-link;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-modal .modal-dialog{
|
||||||
|
width: calc(~"100% - 200px");
|
||||||
|
height: calc(~"100vh - 80px");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px){
|
||||||
|
.NetworkingExtraVars .modal-dialog{
|
||||||
|
width: 700px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-modal .modal-dialog{
|
||||||
|
width: calc(~"100% - 200px");
|
||||||
|
height: calc(~"100vh - 80px");
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-modal .modal-content{
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.NetworkingExtraVars .CodeMirror{
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-modalControls{
|
||||||
|
float: right;
|
||||||
|
margin-top: 15px;
|
||||||
|
button {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
const templateUrl = require('~components/code-mirror/code-mirror.partial.html');
|
||||||
|
|
||||||
|
const CodeMirrorID = 'codemirror-extra-vars';
|
||||||
|
const CodeMirrorModalID = '#CodeMirror-modal';
|
||||||
|
const ParseVariable = 'parseType';
|
||||||
|
const CodeMirrorVar = 'variables';
|
||||||
|
const ParseType = 'yaml';
|
||||||
|
|
||||||
|
function atCodeMirrorController (
|
||||||
|
$scope,
|
||||||
|
strings,
|
||||||
|
ParseTypeChange,
|
||||||
|
ParseVariableString
|
||||||
|
) {
|
||||||
|
const vm = this;
|
||||||
|
|
||||||
|
function init (vars) {
|
||||||
|
$scope.variables = ParseVariableString(_.cloneDeep(vars));
|
||||||
|
$scope.parseType = ParseType;
|
||||||
|
const options = {
|
||||||
|
scope: $scope,
|
||||||
|
variable: CodeMirrorVar,
|
||||||
|
parse_variable: ParseVariable,
|
||||||
|
field_id: CodeMirrorID,
|
||||||
|
readOnly: $scope.disabled
|
||||||
|
};
|
||||||
|
ParseTypeChange(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
function expand () {
|
||||||
|
vm.expanded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function close () {
|
||||||
|
$(CodeMirrorModalID).off('hidden.bs.modal');
|
||||||
|
$(CodeMirrorModalID).modal('hide');
|
||||||
|
$('.popover').popover('hide');
|
||||||
|
vm.expanded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.strings = strings;
|
||||||
|
vm.expanded = false;
|
||||||
|
vm.close = close;
|
||||||
|
vm.expand = expand;
|
||||||
|
if ($scope.init) {
|
||||||
|
$scope.init = init;
|
||||||
|
}
|
||||||
|
init($scope.variables);
|
||||||
|
}
|
||||||
|
|
||||||
|
atCodeMirrorController.$inject = [
|
||||||
|
'$scope',
|
||||||
|
'CodeMirrorStrings',
|
||||||
|
'ParseTypeChange',
|
||||||
|
'ParseVariableString'
|
||||||
|
];
|
||||||
|
|
||||||
|
function atCodeMirrorTextarea () {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
replace: true,
|
||||||
|
transclude: true,
|
||||||
|
templateUrl,
|
||||||
|
controller: atCodeMirrorController,
|
||||||
|
controllerAs: 'vm',
|
||||||
|
scope: {
|
||||||
|
disabled: '@',
|
||||||
|
label: '@',
|
||||||
|
labelClass: '@',
|
||||||
|
tooltip: '@',
|
||||||
|
tooltipPlacement: '@',
|
||||||
|
variables: '@',
|
||||||
|
init: '='
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default atCodeMirrorTextarea;
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<div>
|
||||||
|
<div class="atCodeMirror-label">
|
||||||
|
<div class="atCodeMirror-labelLeftSide">
|
||||||
|
<span class="atCodeMirror-labelText" ng-class="labelClass">
|
||||||
|
{{ label || vm.strings.get('code_mirror.label.VARIABLES') }}
|
||||||
|
</span>
|
||||||
|
<a id=""
|
||||||
|
href=""
|
||||||
|
aw-pop-over="{{ tooltip || vm.strings.get('code_mirror.tooltip.TOOLTIP') }}"
|
||||||
|
data-placement="{{ tooltipPlacement || 'top' }}"
|
||||||
|
data-container="body"
|
||||||
|
over-title="{{ label || vm.strings.get('code_mirror.label.VARIABLES') }}"
|
||||||
|
class="help-link"
|
||||||
|
data-original-title="{{ label || vm.strings.get('code_mirror.label.VARIABLES') }}"
|
||||||
|
title="{{ label || vm.strings.get('code_mirror.label.VARIABLES') }}"
|
||||||
|
tabindex="-1">
|
||||||
|
<i class="fa fa-question-circle"></i>
|
||||||
|
</a>
|
||||||
|
<div class="atCodeMirror-toggleContainer FormToggle-container">
|
||||||
|
<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">
|
||||||
|
{{ vm.strings.get('label.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">
|
||||||
|
{{ vm.strings.get('label.JSON')}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="atCodeMirror-expandTextContainer" ng-click="vm.expand()">{{ vm.strings.get('label.EXPAND') }}</div>
|
||||||
|
</div>
|
||||||
|
<textarea
|
||||||
|
ng-disabled="disabled"
|
||||||
|
rows="6"
|
||||||
|
ng-model="variables"
|
||||||
|
name="variables"
|
||||||
|
class="form-control Form-textArea"
|
||||||
|
id="codemirror-extra-vars">
|
||||||
|
</textarea>
|
||||||
|
<at-code-mirror-modal
|
||||||
|
ng-if="vm.expanded"
|
||||||
|
variables="{{ variables }}"
|
||||||
|
tooltip="{{ tooltip || vm.strings.get('code_mirror.tooltip.TOOLTIP') }}"
|
||||||
|
label="{{ label || vm.strings.get('code_mirror.label.VARIABLES') }}"
|
||||||
|
disabled="{{ disabled || false }}"
|
||||||
|
close-fn="vm.close()">
|
||||||
|
</at-code-mirror-modal>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
function CodeMirrorStrings (BaseString) {
|
||||||
|
BaseString.call(this, 'code_mirror');
|
||||||
|
|
||||||
|
const { t } = this;
|
||||||
|
const ns = this.code_mirror;
|
||||||
|
|
||||||
|
ns.label = {
|
||||||
|
EXTRA_VARIABLES: t.s('EXTRA VARIABLES'),
|
||||||
|
VARIABLES: t.s('VARIABLES'),
|
||||||
|
EXPAND: t.s('EXPAND'),
|
||||||
|
YAML: t.s('YAML'),
|
||||||
|
JSON: t.s('JSON')
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
ns.tooltip = {
|
||||||
|
TOOLTIP: t.s(`
|
||||||
|
<p>
|
||||||
|
Enter inventory variables using either JSON or YAML
|
||||||
|
syntax. Use the radio button to toggle between the two.
|
||||||
|
</p>
|
||||||
|
JSON:
|
||||||
|
<br/>
|
||||||
|
<blockquote>
|
||||||
|
{
|
||||||
|
<br/>"somevar": "somevalue",
|
||||||
|
<br/>"password": "magic"
|
||||||
|
<br/>
|
||||||
|
}
|
||||||
|
</blockquote>
|
||||||
|
YAML:
|
||||||
|
<br/>
|
||||||
|
<blockquote>
|
||||||
|
---
|
||||||
|
<br/>somevar: somevalue
|
||||||
|
<br/>password: magic
|
||||||
|
<br/>
|
||||||
|
</blockquote>
|
||||||
|
<p>
|
||||||
|
View JSON examples at
|
||||||
|
<a href="http://www.json.org" target="_blank">www.json.org</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
View YAML examples at
|
||||||
|
<a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">
|
||||||
|
docs.ansible.com</a>
|
||||||
|
</p>`),
|
||||||
|
TOOLTIP_TITLE: t.s('EXTRA VARIABLES'),
|
||||||
|
JOB_RESULTS: t.s('Read-only view of extra variables added to the job template.')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeMirrorStrings.$inject = ['BaseStringService'];
|
||||||
|
|
||||||
|
export default CodeMirrorStrings;
|
||||||
12
awx/ui/client/lib/components/code-mirror/index.js
Normal file
12
awx/ui/client/lib/components/code-mirror/index.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import codemirror from './code-mirror.directive';
|
||||||
|
import modal from './modal/code-mirror-modal.directive';
|
||||||
|
import strings from './code-mirror.strings';
|
||||||
|
|
||||||
|
const MODULE_NAME = 'at.code.mirror';
|
||||||
|
|
||||||
|
angular.module(MODULE_NAME, [])
|
||||||
|
.directive('atCodeMirror', codemirror)
|
||||||
|
.directive('atCodeMirrorModal', modal)
|
||||||
|
.service('CodeMirrorStrings', strings);
|
||||||
|
|
||||||
|
export default MODULE_NAME;
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
const templateUrl = require('~components/code-mirror/modal/code-mirror-modal.partial.html');
|
||||||
|
|
||||||
|
const CodeMirrorModalID = '#CodeMirror-modal';
|
||||||
|
const CodeMirrorID = 'codemirror-extra-vars-modal';
|
||||||
|
const ParseVariable = 'parseType';
|
||||||
|
const CodeMirrorVar = 'extra_variables';
|
||||||
|
const ParseType = 'yaml';
|
||||||
|
const ModalHeight = '#CodeMirror-modal .modal-dialog';
|
||||||
|
const ModalHeader = '.atCodeMirror-label';
|
||||||
|
const ModalFooter = '.CodeMirror-modalControls';
|
||||||
|
|
||||||
|
function atCodeMirrorModalController (
|
||||||
|
$scope,
|
||||||
|
strings,
|
||||||
|
ParseTypeChange,
|
||||||
|
ParseVariableString
|
||||||
|
) {
|
||||||
|
const vm = this;
|
||||||
|
|
||||||
|
function resize () {
|
||||||
|
const editor = $(`${CodeMirrorModalID} .CodeMirror`)[0].CodeMirror;
|
||||||
|
const height = $(ModalHeight).height() - $(ModalHeader).height() -
|
||||||
|
$(ModalFooter).height() - 100;
|
||||||
|
editor.setSize('100%', height);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle () {
|
||||||
|
$scope.parseTypeChange('parseType', 'extra_variables');
|
||||||
|
setTimeout(resize, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function init () {
|
||||||
|
$(CodeMirrorModalID).modal('show');
|
||||||
|
$scope.extra_variables = ParseVariableString(_.cloneDeep($scope.variables));
|
||||||
|
$scope.parseType = ParseType;
|
||||||
|
const options = {
|
||||||
|
scope: $scope,
|
||||||
|
variable: CodeMirrorVar,
|
||||||
|
parse_variable: ParseVariable,
|
||||||
|
field_id: CodeMirrorID,
|
||||||
|
readOnly: $scope.disabled
|
||||||
|
};
|
||||||
|
ParseTypeChange(options);
|
||||||
|
resize();
|
||||||
|
$(CodeMirrorModalID).on('hidden.bs.modal', $scope.closeFn);
|
||||||
|
$(`${CodeMirrorModalID} .modal-dialog`).resizable({
|
||||||
|
minHeight: 523,
|
||||||
|
minWidth: 600
|
||||||
|
});
|
||||||
|
$(`${CodeMirrorModalID} .modal-dialog`).on('resize', resize);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.strings = strings;
|
||||||
|
vm.toggle = toggle;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
atCodeMirrorModalController.$inject = [
|
||||||
|
'$scope',
|
||||||
|
'CodeMirrorStrings',
|
||||||
|
'ParseTypeChange',
|
||||||
|
'ParseVariableString',
|
||||||
|
];
|
||||||
|
|
||||||
|
function atCodeMirrorModal () {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
replace: true,
|
||||||
|
transclude: true,
|
||||||
|
templateUrl,
|
||||||
|
controller: atCodeMirrorModalController,
|
||||||
|
controllerAs: 'vm',
|
||||||
|
scope: {
|
||||||
|
disabled: '@',
|
||||||
|
label: '@',
|
||||||
|
labelClass: '@',
|
||||||
|
tooltip: '@',
|
||||||
|
variables: '@',
|
||||||
|
closeFn: '&'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default atCodeMirrorModal;
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<div id="CodeMirror-modal" class="CodeMirror-modal modal" role="dialog">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<div class="atCodeMirror-label">
|
||||||
|
<div class="atCodeMirror-labelLeftSide">
|
||||||
|
<span class="atCodeMirror-labelText" ng-class="labelClass">
|
||||||
|
{{ label }}
|
||||||
|
</span>
|
||||||
|
<a id=""
|
||||||
|
href=""
|
||||||
|
aw-pop-over="{{ tooltip }}"
|
||||||
|
data-placement="bottom"
|
||||||
|
data-container="body"
|
||||||
|
over-title="{{ label }}"
|
||||||
|
class="help-link"
|
||||||
|
data-original-title="{{ label }}"
|
||||||
|
title="{{ label }}"
|
||||||
|
tabindex="-1">
|
||||||
|
<i class="fa fa-question-circle"></i>
|
||||||
|
</a>
|
||||||
|
<div class="atCodeMirror-toggleContainer FormToggle-container">
|
||||||
|
<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="vm.toggle()"
|
||||||
|
class="ng-pristine ng-untouched ng-valid ng-not-empty">
|
||||||
|
{{ vm.strings.get('label.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="vm.toggle()"
|
||||||
|
class="ng-pristine ng-untouched ng-valid ng-not-empty">
|
||||||
|
{{ vm.strings.get('label.JSON')}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button type="button" class="close" ng-click="closeFn()">
|
||||||
|
<i class="fa fa-times-circle"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<textarea
|
||||||
|
ng-disabled="disabled"
|
||||||
|
ng-model="extra_variables"
|
||||||
|
name="extra_variables"
|
||||||
|
class="form-control Form-textArea"
|
||||||
|
id="codemirror-extra-vars-modal">
|
||||||
|
</textarea>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="CodeMirror-modalControls">
|
||||||
|
<button ng-click="closeFn()" class="btn btn-sm btn-default">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -34,6 +34,7 @@ import tab from '~components/tabs/tab.directive';
|
|||||||
import tabGroup from '~components/tabs/group.directive';
|
import tabGroup from '~components/tabs/group.directive';
|
||||||
import topNavItem from '~components/layout/top-nav-item.directive';
|
import topNavItem from '~components/layout/top-nav-item.directive';
|
||||||
import truncate from '~components/truncate/truncate.directive';
|
import truncate from '~components/truncate/truncate.directive';
|
||||||
|
import atCodeMirror from '~components/code-mirror';
|
||||||
|
|
||||||
import BaseInputController from '~components/input/base.controller';
|
import BaseInputController from '~components/input/base.controller';
|
||||||
import ComponentsStrings from '~components/components.strings';
|
import ComponentsStrings from '~components/components.strings';
|
||||||
@@ -42,7 +43,8 @@ const MODULE_NAME = 'at.lib.components';
|
|||||||
|
|
||||||
angular
|
angular
|
||||||
.module(MODULE_NAME, [
|
.module(MODULE_NAME, [
|
||||||
atLibServices
|
atLibServices,
|
||||||
|
atCodeMirror
|
||||||
])
|
])
|
||||||
.directive('atActionGroup', actionGroup)
|
.directive('atActionGroup', actionGroup)
|
||||||
.directive('atDivider', divider)
|
.directive('atDivider', divider)
|
||||||
|
|||||||
@@ -5,10 +5,15 @@
|
|||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
export default
|
export default
|
||||||
['$scope', '$state', '$stateParams', 'GenerateForm', 'ParseTypeChange', 'HostsService',
|
['$scope', 'HostsService',
|
||||||
function($scope, $state, $stateParams, GenerateForm, ParseTypeChange, HostsService){
|
function($scope, HostsService){
|
||||||
|
|
||||||
$scope.parseType = 'yaml';
|
function codemirror () {
|
||||||
|
return {
|
||||||
|
init:{}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
$scope.codeMirror = new codemirror();
|
||||||
$scope.formCancel = function(){
|
$scope.formCancel = function(){
|
||||||
$scope.$parent.$broadcast('awxNet-closeDetailsPanel');
|
$scope.$parent.$broadcast('awxNet-closeDetailsPanel');
|
||||||
};
|
};
|
||||||
@@ -30,7 +35,6 @@
|
|||||||
$scope.saveConfirmed = false;
|
$scope.saveConfirmed = false;
|
||||||
}, 3000);
|
}, 3000);
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.$parent.$on('awxNet-showDetails', (e, data, canAdd) => {
|
$scope.$parent.$on('awxNet-showDetails', (e, data, canAdd) => {
|
||||||
@@ -40,5 +44,8 @@
|
|||||||
} else {
|
} else {
|
||||||
$scope.item = data;
|
$scope.item = data;
|
||||||
}
|
}
|
||||||
|
if ($scope.codeMirror.init) {
|
||||||
|
$scope.codeMirror.init($scope.item.variables);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}];
|
}];
|
||||||
|
|||||||
@@ -31,7 +31,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group Form-formGroup Form-formGroup--fullWidth">
|
<div class="form-group Form-formGroup Form-formGroup--fullWidth">
|
||||||
<awx-net-extra-vars item="item"></awx-net-extra-vars>
|
<at-code-mirror
|
||||||
|
disabled="true"
|
||||||
|
variables="{{ item.variables }}"
|
||||||
|
tooltip-placement="left"
|
||||||
|
init="codeMirror.init">
|
||||||
|
</at-code-mirror>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div class="buttons Form-buttons" id="host_controls">
|
<div class="buttons Form-buttons" id="host_controls">
|
||||||
|
|||||||
@@ -5,9 +5,7 @@
|
|||||||
*************************************************/
|
*************************************************/
|
||||||
|
|
||||||
import awxNetDetailsPanel from './details.directive';
|
import awxNetDetailsPanel from './details.directive';
|
||||||
import awxNetExtraVars from './network-extra-vars/network-extra-vars.directive';
|
|
||||||
|
|
||||||
export default
|
export default
|
||||||
angular.module('networkDetailsDirective', [])
|
angular.module('networkDetailsDirective', [])
|
||||||
.directive('awxNetDetailsPanel', awxNetDetailsPanel)
|
.directive('awxNetDetailsPanel', awxNetDetailsPanel);
|
||||||
.directive('awxNetExtraVars', awxNetExtraVars);
|
|
||||||
|
|||||||
@@ -1,168 +0,0 @@
|
|||||||
.NetworkingExtraVarsLabel{
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVars-extraVarsLabelContainer{
|
|
||||||
flex: 1 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVars-expandTextContainer{
|
|
||||||
flex: 1 0 auto;
|
|
||||||
text-align: right;
|
|
||||||
font-weight: normal;
|
|
||||||
color: @default-link;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noselect {
|
|
||||||
-webkit-touch-callout: none; /* iOS Safari */
|
|
||||||
-webkit-user-select: none; /* Chrome/Safari/Opera */
|
|
||||||
-khtml-user-select: none; /* Konqueror */
|
|
||||||
-moz-user-select: none; /* Firefox */
|
|
||||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
|
||||||
user-select: none; /* Non-prefixed version, currently
|
|
||||||
not supported by any browser */
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 768px){
|
|
||||||
.NetworkingExtraVars .modal-dialog{
|
|
||||||
width: 700px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVarsModal .modal-dialog{
|
|
||||||
width: calc(~"100% - 200px");
|
|
||||||
height: calc(~"100vh - 80px");
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVarsModal .modal-content{
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVars .CodeMirror{
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVars-close:hover{
|
|
||||||
color: @btn-txt;
|
|
||||||
background-color: @btn-bg-hov;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVars-body{
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVars-tab:hover {
|
|
||||||
color: @btn-txt;
|
|
||||||
background-color: @btn-bg-hov;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVars-tab--selected{
|
|
||||||
color: @btn-txt-sel!important;
|
|
||||||
background-color: @default-icon!important;
|
|
||||||
border-color: @default-icon!important;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVars-view--container{
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVars .modal-footer{
|
|
||||||
border: 0;
|
|
||||||
margin-top: 0px;
|
|
||||||
padding-top: 5px;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVars-controls{
|
|
||||||
float: right;
|
|
||||||
margin-top: 15px;
|
|
||||||
button {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVars-header{
|
|
||||||
padding-bottom: 15px;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVars-title{
|
|
||||||
color: @default-interface-txt;
|
|
||||||
font-weight: 600;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVarsModal .modal-body{
|
|
||||||
padding: 0px!important;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVars-nav{
|
|
||||||
padding-top: 12px;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVars-field{
|
|
||||||
margin-bottom: 8px;
|
|
||||||
flex: 0 1 12em;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVars-field--label{
|
|
||||||
text-transform: uppercase;
|
|
||||||
flex: 0 1 80px;
|
|
||||||
max-width: 80px;
|
|
||||||
min-width: 80px;
|
|
||||||
font-size: 12px;
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVars-field{
|
|
||||||
.OnePlusTwo-left--detailsRow;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVars-field--content{
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVars-field--monospaceContent{
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
.NetworkingExtraVars-button:disabled {
|
|
||||||
pointer-events: all!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVars-numberColumnPreload {
|
|
||||||
background-color: @default-list-header-bg;
|
|
||||||
height: 198px;
|
|
||||||
border-right: 1px solid #ccc;
|
|
||||||
width: 30px;
|
|
||||||
position: fixed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVars-numberColumn {
|
|
||||||
background-color: @default-list-header-bg;
|
|
||||||
border-right: 1px solid #ccc;
|
|
||||||
border-bottom-left-radius: 5px;
|
|
||||||
color: #999;
|
|
||||||
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
|
|
||||||
position: fixed;
|
|
||||||
padding: 4px 3px 0 5px;
|
|
||||||
text-align: right;
|
|
||||||
white-space: nowrap;
|
|
||||||
width: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVars-numberColumn--second{
|
|
||||||
padding-top:0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVars-noJson{
|
|
||||||
align-items: center;
|
|
||||||
background-color: @default-no-items-bord;
|
|
||||||
border: 1px solid @default-icon-hov;
|
|
||||||
border-radius: 5px;
|
|
||||||
color: @b7grey;
|
|
||||||
display: flex;
|
|
||||||
height: 200px;
|
|
||||||
justify-content: center;
|
|
||||||
text-transform: uppercase;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.NetworkingExtraVarsModal .CodeMirror{
|
|
||||||
max-height: none;
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
/*************************************************
|
|
||||||
* Copyright (c) 2018 Ansible, Inc.
|
|
||||||
*
|
|
||||||
* All Rights Reserved
|
|
||||||
*************************************************/
|
|
||||||
|
|
||||||
const templateUrl = require('~network-ui/network-details/network-extra-vars/network-extra-vars.partial.html');
|
|
||||||
|
|
||||||
export default [ 'ParseTypeChange', 'ParseVariableString',
|
|
||||||
function(ParseTypeChange, ParseVariableString) {
|
|
||||||
return {
|
|
||||||
scope:{
|
|
||||||
item: "="
|
|
||||||
},
|
|
||||||
templateUrl,
|
|
||||||
restrict: 'E',
|
|
||||||
link(scope){
|
|
||||||
scope.networkingExtraVarsModalOpen = true;
|
|
||||||
function init(){
|
|
||||||
if(scope.item && scope.item.host_id){
|
|
||||||
scope.variables = ParseVariableString(scope.item.variables);
|
|
||||||
scope.parseType = 'yaml';
|
|
||||||
ParseTypeChange({
|
|
||||||
scope: scope,
|
|
||||||
field_id: 'network_host_variables',
|
|
||||||
variable: 'variables',
|
|
||||||
readOnly: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scope.$watch('item', function(){
|
|
||||||
init();
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.closeExtraVarModal = function() {
|
|
||||||
// Unbind the listener so it doesn't fire when we close the modal via navigation
|
|
||||||
$('.CodeMirror')[1].remove();
|
|
||||||
$('#NetworkingExtraVarsModal').off('hidden.bs.modal');
|
|
||||||
$('#NetworkingExtraVarsModal').modal('hide');
|
|
||||||
scope.networkingExtraVarsModalOpen = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
scope.openExtraVarsModal = function(){
|
|
||||||
scope.networkingExtraVarsModalOpen = true;
|
|
||||||
$('#NetworkingExtraVarsModal').modal('show');
|
|
||||||
|
|
||||||
$('.modal-dialog').on('resize', function(){
|
|
||||||
resize();
|
|
||||||
});
|
|
||||||
scope.extra_variables = ParseVariableString(_.cloneDeep(scope.item.variables));
|
|
||||||
scope.parseType = 'yaml';
|
|
||||||
ParseTypeChange({
|
|
||||||
scope: scope,
|
|
||||||
field_id: 'NetworkingExtraVars-codemirror',
|
|
||||||
variable: 'extra_variables',
|
|
||||||
readOnly: true
|
|
||||||
});
|
|
||||||
resize();
|
|
||||||
};
|
|
||||||
|
|
||||||
function resize(){
|
|
||||||
let editor = $('.CodeMirror')[1].CodeMirror;
|
|
||||||
let height = $('#NetworkingExtraVarsModalDialog').height() - $('.NetworkingExtraVars-header').height() - $('.NetworkingExtraVars-controls').height() - 110;
|
|
||||||
editor.setSize("100%", height);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}];
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
<label class="NetworkingExtraVarsLabel" for="variables">
|
|
||||||
<div class="NetworkingExtraVars-extraVarsLabelContainer">
|
|
||||||
<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 /> "somevar": "somevalue",<br /> "password": "magic"<br /> }</blockquote>
|
|
||||||
YAML:<br />
|
|
||||||
<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>
|
|
||||||
<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p><p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">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>
|
|
||||||
</div>
|
|
||||||
<div class="NetworkingExtraVars-expandTextContainer" ng-click="openExtraVarsModal()">EXPAND</div>
|
|
||||||
</label>
|
|
||||||
<textarea readonly rows="6" disabled="disabled" ng-model="variables" name="variables" class="form-control Form-textArea Form-formGroup--fullWidth" id="network_host_variables"></textarea>
|
|
||||||
|
|
||||||
|
|
||||||
<div ng-if="networkingExtraVarsModalOpen" id="NetworkingExtraVarsModal" class="NetworkingExtraVarsModal modal" role="dialog">
|
|
||||||
<div id="NetworkingExtraVarsModalDialog" class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<!-- modal body -->
|
|
||||||
<div class="modal-body">
|
|
||||||
<div class="NetworkingExtraVars-header">
|
|
||||||
<span class="NetworkingExtraVars-title">{{item.name}}</span>
|
|
||||||
<button ng-click="closeExtraVarModal()" type="button" class="close">
|
|
||||||
<i class="fa fa-times-circle"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="NetworkingExtraVars-codemirrorContainer">
|
|
||||||
<!-- <textarea ng-hide="no_json" ng-model="variables" id="NetworkingExtraVars-codemirror" class="NetworkingExtraVars-codemirror"></textarea> -->
|
|
||||||
<label class="NetworkingExtraVarsModalLabel" 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 /> "somevar": "somevalue",<br /> "password": "magic"<br /> }</blockquote>
|
|
||||||
YAML:<br />
|
|
||||||
<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>
|
|
||||||
<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p><p>View YAML examples at <a href="http://docs.ansible.com/YAMLSyntax.html" target="_blank">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 readonly disabled ng-model="extra_variables" name="extra_variables" class="form-control Form-textArea Form-formGroup--fullWidth" id="NetworkingExtraVars-codemirror"></textarea>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div ng-if="no_json" class="NetworkingExtraVars-noJson" translate>No JSON data returned by the module</div>
|
|
||||||
<div class="NetworkingExtraVars-controls">
|
|
||||||
<button ng-click="closeExtraVarModal()" class="btn btn-sm btn-default NetworkingExtraVars-close">Close</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
/* Copyright (c) 2017 Red Hat, Inc. */
|
/* Copyright (c) 2017 Red Hat, Inc. */
|
||||||
@import 'network-nav/network.nav.block.less';
|
@import 'network-nav/network.nav.block.less';
|
||||||
@import 'network-details/details.block.less';
|
@import 'network-details/details.block.less';
|
||||||
@import 'network-details/network-extra-vars/network-extra-vars.block.less';
|
|
||||||
@import 'zoom-widget/zoom.block.less';
|
@import 'zoom-widget/zoom.block.less';
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
|
|||||||
Reference in New Issue
Block a user