mirror of
https://github.com/ansible/awx.git
synced 2026-05-08 01:47:35 -02:30
Add support for dynamic select inputs
This commit is contained in:
@@ -11,6 +11,7 @@ function AddCredentialsController (models, $state) {
|
|||||||
|
|
||||||
vm.form.credential_type._data = credentialType.get('results');
|
vm.form.credential_type._data = credentialType.get('results');
|
||||||
vm.form.credential_type._placeholder = 'SELECT A TYPE';
|
vm.form.credential_type._placeholder = 'SELECT A TYPE';
|
||||||
|
vm.form.credential_type._format = 'grouped-object';
|
||||||
vm.form.credential_type._display = 'name';
|
vm.form.credential_type._display = 'name';
|
||||||
vm.form.credential_type._key = 'id';
|
vm.form.credential_type._key = 'id';
|
||||||
vm.form.credential_type._exp = 'type as type.name group by type.kind for type in state._data';
|
vm.form.credential_type._exp = 'type as type.name group by type.kind for type in state._data';
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import inputSelect from './input/select.directive';
|
|||||||
import inputSecret from './input/secret.directive';
|
import inputSecret from './input/secret.directive';
|
||||||
import inputText from './input/text.directive';
|
import inputText from './input/text.directive';
|
||||||
import inputTextarea from './input/textarea.directive';
|
import inputTextarea from './input/textarea.directive';
|
||||||
|
import inputTextareaSecret from './input/textarea-secret.directive';
|
||||||
import panel from './panel/panel.directive';
|
import panel from './panel/panel.directive';
|
||||||
import panelHeading from './panel/heading.directive';
|
import panelHeading from './panel/heading.directive';
|
||||||
import panelBody from './panel/body.directive';
|
import panelBody from './panel/body.directive';
|
||||||
@@ -31,6 +32,7 @@ angular
|
|||||||
.directive('atInputSelect', inputSelect)
|
.directive('atInputSelect', inputSelect)
|
||||||
.directive('atInputText', inputText)
|
.directive('atInputText', inputText)
|
||||||
.directive('atInputTextarea', inputTextarea)
|
.directive('atInputTextarea', inputTextarea)
|
||||||
|
.directive('atInputTextareaSecret', inputTextareaSecret)
|
||||||
.directive('atPanel', panel)
|
.directive('atPanel', panel)
|
||||||
.directive('atPanelHeading', panelHeading)
|
.directive('atPanelHeading', panelHeading)
|
||||||
.directive('atPanelBody', panelBody)
|
.directive('atPanelBody', panelBody)
|
||||||
|
|||||||
@@ -56,33 +56,62 @@ function AtInputGroupController ($scope, $compile) {
|
|||||||
let group = [];
|
let group = [];
|
||||||
|
|
||||||
inputs.forEach((input, i) => {
|
inputs.forEach((input, i) => {
|
||||||
if (input.type === 'string') {
|
input = Object.assign(input, vm.getComponentType(input));
|
||||||
if (input.secret && input.multiline) {
|
|
||||||
input._component = 'at-input-textarea';
|
|
||||||
} else if (input.secret) {
|
|
||||||
input._component = 'at-input-secret';
|
|
||||||
} else if (input.multiline) {
|
|
||||||
input._component = 'at-input-textarea';
|
|
||||||
} else {
|
|
||||||
input._component = 'at-input-text';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
group.push(Object.assign({
|
group.push(Object.assign({
|
||||||
_element: vm.createElement(input, i),
|
_element: vm.createElement(input, i),
|
||||||
_key: 'inputs',
|
_key: 'inputs',
|
||||||
_group: true
|
_group: true,
|
||||||
|
_groupIndex: i
|
||||||
}, input));
|
}, input));
|
||||||
});
|
});
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vm.getComponentType = input => {
|
||||||
|
let config = {};
|
||||||
|
|
||||||
|
if (input.type === 'string') {
|
||||||
|
if (!input.multiline) {
|
||||||
|
if (input.secret) {
|
||||||
|
config._component = 'at-input-text';
|
||||||
|
} else {
|
||||||
|
config._component = 'at-input-secret';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config._expand = true;
|
||||||
|
|
||||||
|
if (input.secret) {
|
||||||
|
config._component = 'at-input-textarea-secret';
|
||||||
|
} else {
|
||||||
|
config._component = 'at-input-textarea';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.format === 'ssh_private_key') {
|
||||||
|
config._format = 'ssh-key';
|
||||||
|
}
|
||||||
|
} else if (input.type === 'number') {
|
||||||
|
config._component = 'at-input-number';
|
||||||
|
} else if (input.choices) {
|
||||||
|
config._component = 'at-input-select';
|
||||||
|
config._format = 'array';
|
||||||
|
config._data = input.choices;
|
||||||
|
config._exp = 'index as choice for (index, choice) in state._data';
|
||||||
|
} else {
|
||||||
|
throw new Error('Unsupported input type: ' + input.type)
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
};
|
||||||
|
|
||||||
vm.createElement = (input, index) => {
|
vm.createElement = (input, index) => {
|
||||||
let tabindex = Number(scope.tab) + index;
|
let tabindex = Number(scope.tab) + index;
|
||||||
|
let col = input._expand ? 12 : scope.col;
|
||||||
|
|
||||||
let element =
|
let element =
|
||||||
`<${input._component} col="${scope.col}" tab="${tabindex}"
|
`<${input._component} col="${col}" tab="${tabindex}"
|
||||||
state="${state._reference}._group[${index}]">
|
state="${state._reference}._group[${index}]">
|
||||||
</${input._component}>`;
|
</${input._component}>`;
|
||||||
|
|
||||||
@@ -91,19 +120,35 @@ function AtInputGroupController ($scope, $compile) {
|
|||||||
|
|
||||||
vm.insert = group => {
|
vm.insert = group => {
|
||||||
let container = document.createElement('div');
|
let container = document.createElement('div');
|
||||||
let divider = angular.element(`<div class="at-InputGroup-divider"></div>`)[0];
|
let col = 1;
|
||||||
|
let colPerRow = 12 / scope.col;
|
||||||
|
let isDivided = true;
|
||||||
|
|
||||||
for (let i = 0; i < group.length; i++) {
|
group.forEach((input, i) => {
|
||||||
if (i !== 0 && (i % (12 / scope.col)) === 0) {
|
if (input._expand && !isDivided) {
|
||||||
container.appendChild(divider);
|
container.appendChild(vm.createInputDivider());
|
||||||
}
|
}
|
||||||
|
|
||||||
container.appendChild(group[i]._element[0]);
|
container.appendChild(input._element[0]);
|
||||||
}
|
|
||||||
|
if ((input._expand || col % colPerRow === 0) && i !== group.length -1) {
|
||||||
|
container.appendChild(vm.createInputDivider());
|
||||||
|
isDivided = true;
|
||||||
|
col = 0;
|
||||||
|
} else {
|
||||||
|
isDivided = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
col++;
|
||||||
|
});
|
||||||
|
|
||||||
element.appendChild(container);
|
element.appendChild(container);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vm.createInputDivider = () => {
|
||||||
|
return angular.element(`<div class="at-InputGroup-divider"></div>`)[0];
|
||||||
|
};
|
||||||
|
|
||||||
vm.compile = group => {
|
vm.compile = group => {
|
||||||
group.forEach(component => $compile(component._element[0])(scope.$parent));
|
group.forEach(component => $compile(component._element[0])(scope.$parent));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,6 +46,16 @@ function AtInputSelectController (baseInputController, eventService) {
|
|||||||
|
|
||||||
scope.$on('$destroy', () => eventService.remove(listeners));
|
scope.$on('$destroy', () => eventService.remove(listeners));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vm.updateDisplayModel = () => {
|
||||||
|
if (scope.state._format === 'array') {
|
||||||
|
scope.displayModel = scope.state._data[scope.state._value];
|
||||||
|
} else if (scope.state._format === 'grouped-object') {
|
||||||
|
scope.displayModel = scope.state._value[scope.state._display];
|
||||||
|
} else {
|
||||||
|
throw new Error('Unsupported display model type');
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
AtInputSelectController.$inject = ['BaseInputController', 'EventService'];
|
AtInputSelectController.$inject = ['BaseInputController', 'EventService'];
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
<input type="text"
|
<input type="text"
|
||||||
class="form-control at-Input at-InputSelect-input"
|
class="form-control at-Input at-InputSelect-input"
|
||||||
placeholder="{{state._placeholder || undefined }}"
|
placeholder="{{state._placeholder || undefined }}"
|
||||||
ng-class="{ 'at-Input--rejected': state.rejected }"
|
ng-class="{ 'at-Input--rejected': state._rejected }"
|
||||||
ng-model="state._value[state._display]"
|
ng-model="displayModel"
|
||||||
ng-disabled="state._disabled || form.disabled"
|
ng-disabled="state._disabled || form.disabled"
|
||||||
ng-change="vm.check()" />
|
ng-change="vm.check()" />
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
ng-model="state._value"
|
ng-model="state._value"
|
||||||
ng-attr-tabindex="{{ tab || undefined }}"
|
ng-attr-tabindex="{{ tab || undefined }}"
|
||||||
ng-disabled="state._disabled || form.disabled"
|
ng-disabled="state._disabled || form.disabled"
|
||||||
|
ng-change="vm.updateDisplayModel()"
|
||||||
ng-options="{{ state._exp }}"></select>
|
ng-options="{{ state._exp }}"></select>
|
||||||
|
|
||||||
<i class="fa" ng-class="{ 'fa-chevron-down': !open, 'fa-chevron-up': open }"></i>
|
<i class="fa" ng-class="{ 'fa-chevron-down': !open, 'fa-chevron-up': open }"></i>
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
function atInputTextareaSecretLink (scope, element, attrs, controllers) {
|
||||||
|
let formController = controllers[0];
|
||||||
|
let inputController = controllers[1];
|
||||||
|
|
||||||
|
if (scope.tab === '1') {
|
||||||
|
element.find('input')[0].focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
inputController.init(scope, element, formController);
|
||||||
|
}
|
||||||
|
|
||||||
|
function AtInputTextareaSecretController (baseInputController) {
|
||||||
|
let vm = this || {};
|
||||||
|
|
||||||
|
vm.init = (scope, element, form) => {
|
||||||
|
baseInputController.call(vm, 'input', scope, element, form);
|
||||||
|
|
||||||
|
vm.check();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
AtInputTextareaSecretController.$inject = ['BaseInputController'];
|
||||||
|
|
||||||
|
function atInputTextareaSecret (pathService) {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
transclude: true,
|
||||||
|
replace: true,
|
||||||
|
require: ['^^atForm', 'atInputTextareaSecret'],
|
||||||
|
templateUrl: pathService.getPartialPath('components/input/textarea-secret'),
|
||||||
|
controller: AtInputTextareaSecretController,
|
||||||
|
controllerAs: 'vm',
|
||||||
|
link: atInputTextareaSecretLink,
|
||||||
|
scope: {
|
||||||
|
state: '=',
|
||||||
|
col: '@',
|
||||||
|
tab: '@'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
atInputTextareaSecret.$inject = ['PathService'];
|
||||||
|
|
||||||
|
export default atInputTextareaSecret;
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<div class="col-sm-{{::col}}">
|
||||||
|
<div class="form-group at-u-flat">
|
||||||
|
<at-input-label></at-input-label>
|
||||||
|
|
||||||
|
<textarea class="form-control at-Input"
|
||||||
|
ng-model="state._value"
|
||||||
|
ng-class="{ 'at-Input--rejected': state._rejected }"
|
||||||
|
ng-attr-maxlength="{{ state.max_length || undefined }}"
|
||||||
|
ng-attr-tabindex="{{ tab || undefined }}"
|
||||||
|
ng-attr-placeholder="{{::state._placeholder || undefined }}"
|
||||||
|
ng-change="vm.check()"
|
||||||
|
ng-disabled="state._disabled || form.disabled" /></textarea>
|
||||||
|
|
||||||
|
<at-input-message></at-input-message>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -19,7 +19,7 @@ function createFormSchema (type, config) {
|
|||||||
function CredentialModel (method, id) {
|
function CredentialModel (method, id) {
|
||||||
BaseModel.call(this, 'credentials');
|
BaseModel.call(this, 'credentials');
|
||||||
|
|
||||||
this.createFormSchema = createFormSchema;
|
this.createFormSchema = createFormSchema.bind(this);
|
||||||
|
|
||||||
return this.request(method, id)
|
return this.request(method, id)
|
||||||
.then(() => this);
|
.then(() => this);
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ function mergeInputProperties (type) {
|
|||||||
function CredentialTypeModel (method, id) {
|
function CredentialTypeModel (method, id) {
|
||||||
BaseModel.call(this, 'credential_types');
|
BaseModel.call(this, 'credential_types');
|
||||||
|
|
||||||
this.categorizeByKind = categorizeByKind;
|
this.categorizeByKind = categorizeByKind.bind(this);
|
||||||
this.mergeInputProperties = mergeInputProperties;
|
this.mergeInputProperties = mergeInputProperties.bind(this);
|
||||||
|
|
||||||
return this.request(method, id)
|
return this.request(method, id)
|
||||||
.then(() => this);
|
.then(() => this);
|
||||||
|
|||||||
Reference in New Issue
Block a user