mirror of
https://github.com/ZwareBear/awx.git
synced 2026-04-25 17:31:48 -05:00
Adds atCdeMirror directive
This commit adds a new component to be used for showing CodeMirror instances, along with an expandable capability to view more variables. It also removes the previous directive for the Network UI that used to include this functionality.
This commit is contained in:
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 CodeMirrorEventListener = 'CodeMirror-init';
|
||||
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;
|
||||
init($scope.variables);
|
||||
$scope.$on(CodeMirrorEventListener, (e, vars) => {
|
||||
init(vars);
|
||||
});
|
||||
}
|
||||
|
||||
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: '@'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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,79 @@
|
||||
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);
|
||||
}
|
||||
|
||||
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>
|
||||
Reference in New Issue
Block a user