mirror of
https://github.com/ansible/awx.git
synced 2026-04-12 13:39:24 -02:30
Add working dynamic component insertion
This commit is contained in:
@@ -23,7 +23,9 @@ function AddCredentialsController (models) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
vm.dynamic = {
|
vm.dynamic = {
|
||||||
model: credential
|
getInputs: credentialType.getTypeFromName,
|
||||||
|
source: vm.kind,
|
||||||
|
reference: 'vm.dynamic'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,7 @@
|
|||||||
<at-input-text col="4" config="vm.description"></at-input-text>
|
<at-input-text col="4" config="vm.description"></at-input-text>
|
||||||
<at-input-select col="4" config="vm.kind"></at-input-select>
|
<at-input-select col="4" config="vm.kind"></at-input-select>
|
||||||
|
|
||||||
<at-dynamic-input-group col="4" config="vm.dynamic" watch="vm.kind">
|
<at-dynamic-input-group col="4" config="vm.dynamic"></at-dynamic-input-group>
|
||||||
</at-dynamic-input-group>
|
|
||||||
|
|
||||||
<at-action-group col="12" pos="right">
|
<at-action-group col="12" pos="right">
|
||||||
<at-form-action type="cancel"></at-form-action>
|
<at-form-action type="cancel"></at-form-action>
|
||||||
|
|||||||
@@ -1,36 +1,100 @@
|
|||||||
function link (scope, el, attrs, controllers) {
|
function link (scope, el, attrs, controllers) {
|
||||||
let dynamicController = controllers[0];
|
let formController = controllers[0];
|
||||||
|
let dynamicController = controllers[1];
|
||||||
|
el = el[0];
|
||||||
|
|
||||||
dynamicController.init(scope);
|
dynamicController.init(scope, formController, el);
|
||||||
}
|
}
|
||||||
|
|
||||||
function atDynamicInputGroupController () {
|
function atDynamicInputGroupController ($scope, $compile) {
|
||||||
let vm = this || {};
|
let vm = this || {};
|
||||||
|
|
||||||
let state;
|
let state;
|
||||||
let scope;
|
let scope;
|
||||||
let input;
|
let source;
|
||||||
let form;
|
let form;
|
||||||
|
let el;
|
||||||
|
|
||||||
vm.init = (_scope_) => {
|
vm.init = (_scope_, _form_, _el_) => {
|
||||||
|
form = _form_;
|
||||||
scope = _scope_;
|
scope = _scope_;
|
||||||
console.log(scope.watch);
|
el = _el_;
|
||||||
// scope.form = form.use('input', state);
|
|
||||||
|
scope.config.state = scope.config.state || {};
|
||||||
|
state = scope.config.state;
|
||||||
|
source = scope.config.source;
|
||||||
|
|
||||||
|
$scope.$watch('config.source.state.value', vm.update);
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.update = () => {
|
||||||
|
if (!source.state.value || source.state.value === state.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.value = source.state.value;
|
||||||
|
|
||||||
|
let inputs = scope.config.getInputs(source.state.value);
|
||||||
|
let components = vm.createComponentConfigs(inputs);
|
||||||
|
|
||||||
|
vm.insert(components);
|
||||||
|
scope.config.components = components;
|
||||||
|
vm.compile(components);
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.createComponentConfigs = inputs => {
|
||||||
|
let components = [];
|
||||||
|
|
||||||
|
inputs.forEach((input, i) => {
|
||||||
|
if (input.type === 'string') {
|
||||||
|
if (input.secret) {
|
||||||
|
input.component = 'at-input-secret';
|
||||||
|
} else if (input.multiline) {
|
||||||
|
input.component = 'at-input-textarea';
|
||||||
|
} else {
|
||||||
|
input.component = 'at-input-text';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let html = angular.element(`
|
||||||
|
<${input.component}
|
||||||
|
col="${scope.col}"
|
||||||
|
config="${scope.config.reference}.components[${i}]">
|
||||||
|
</${input.component}>
|
||||||
|
`);
|
||||||
|
|
||||||
|
components.push({
|
||||||
|
options: input,
|
||||||
|
html
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return components;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.insert = components => {
|
||||||
|
components.forEach(component => el.appendChild(component.html[0]));
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.compile = components => {
|
||||||
|
components.forEach(component => $compile(component.html[0])(scope.$parent));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atDynamicInputGroupController.$inject = ['$scope', '$compile'];
|
||||||
|
|
||||||
function atDynamicInputGroup (pathService) {
|
function atDynamicInputGroup (pathService) {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
replace: true,
|
replace: true,
|
||||||
require: ['atDynamicInputGroup'],
|
require: ['^^atForm', 'atDynamicInputGroup'],
|
||||||
templateUrl: pathService.getPartialPath('components/dynamic/input-group'),
|
templateUrl: pathService.getPartialPath('components/dynamic/input-group'),
|
||||||
controller: atDynamicInputGroupController,
|
controller: atDynamicInputGroupController,
|
||||||
controllerAs: 'vm',
|
controllerAs: 'vm',
|
||||||
link,
|
link,
|
||||||
scope: {
|
scope: {
|
||||||
config: '=',
|
config: '=',
|
||||||
watch: '='
|
col: '@'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,2 @@
|
|||||||
<div>
|
<div>
|
||||||
{{ watch.state.value }}
|
|
||||||
{{ watch.data[watch.state.value] }}
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ function atFormActionController ($state) {
|
|||||||
|
|
||||||
let form;
|
let form;
|
||||||
let scope;
|
let scope;
|
||||||
let el;
|
|
||||||
let state;
|
let state;
|
||||||
|
|
||||||
vm.init = (_form_, _scope_) => {
|
vm.init = (_form_, _scope_) => {
|
||||||
|
|||||||
@@ -1,59 +1,44 @@
|
|||||||
function AtFormController () {
|
function AtFormController () {
|
||||||
let vm = this || {};
|
let vm = this || {};
|
||||||
|
|
||||||
vm.inputs = [];
|
vm.components = [];
|
||||||
vm.actions = [];
|
|
||||||
vm.state = {
|
vm.state = {
|
||||||
isValid: false
|
isValid: false
|
||||||
};
|
};
|
||||||
|
|
||||||
vm.use = (type, component, el) => {
|
vm.use = (type, component, el) => {
|
||||||
let state;
|
return vm.trackComponent(type, component, el);
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 'input':
|
|
||||||
state = vm.trackInput(component, el);
|
|
||||||
break;
|
|
||||||
case 'action':
|
|
||||||
state = vm.trackAction(component, el);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error('An at-form cannot use component type:', type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
vm.trackInput = (input, el) => {
|
vm.trackComponent = (type, component, el) => {
|
||||||
let form = {
|
let meta = {
|
||||||
|
el,
|
||||||
|
type,
|
||||||
state: vm.state,
|
state: vm.state,
|
||||||
disabled: false
|
disabled: false,
|
||||||
|
tabindex: vm.components.length + 1
|
||||||
};
|
};
|
||||||
|
|
||||||
vm.inputs.push(input)
|
if (!vm.components.length) {
|
||||||
|
el.focus();
|
||||||
|
}
|
||||||
|
|
||||||
return form;
|
vm.components.push(meta)
|
||||||
};
|
|
||||||
|
|
||||||
vm.trackAction = action => {
|
return meta;
|
||||||
let form = {
|
|
||||||
state: vm.state,
|
|
||||||
disabled: false
|
|
||||||
};
|
|
||||||
|
|
||||||
vm.actions.push(action);
|
|
||||||
|
|
||||||
return form;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
vm.validate = () => {
|
vm.validate = () => {
|
||||||
let isValid = true;
|
let isValid = true;
|
||||||
|
|
||||||
vm.inputs.forEach(input => {
|
vm.components
|
||||||
if (!input.isValid) {
|
.filter(component => component.type === 'input')
|
||||||
isValid = false;
|
.forEach(input => {
|
||||||
}
|
if (input.isValid) {
|
||||||
});
|
isValid = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return isValid;
|
return isValid;
|
||||||
};
|
};
|
||||||
@@ -71,6 +56,10 @@ function AtFormController () {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function link (scope, el, attrs, controller, fn) {
|
||||||
|
//console.log(fn);
|
||||||
|
}
|
||||||
|
|
||||||
function atForm (pathService) {
|
function atForm (pathService) {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
@@ -78,6 +67,7 @@ function atForm (pathService) {
|
|||||||
templateUrl: pathService.getPartialPath('components/form/form'),
|
templateUrl: pathService.getPartialPath('components/form/form'),
|
||||||
controller: AtFormController,
|
controller: AtFormController,
|
||||||
controllerAs: 'vm',
|
controllerAs: 'vm',
|
||||||
|
link,
|
||||||
scope: {
|
scope: {
|
||||||
config: '='
|
config: '='
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,15 +25,11 @@ function AtInputSelectController (eventService) {
|
|||||||
scope.config.state = scope.config.state || {};
|
scope.config.state = scope.config.state || {};
|
||||||
state = scope.config.state;
|
state = scope.config.state;
|
||||||
|
|
||||||
if (scope.tab === 1) {
|
|
||||||
select.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
state.isValid = state.isValid || false;
|
state.isValid = state.isValid || false;
|
||||||
state.message = state.message || '';
|
state.message = state.message || '';
|
||||||
state.required = scope.config.options.required || false;
|
state.required = scope.config.options.required || false;
|
||||||
|
|
||||||
scope.form = form.use('input', state);
|
scope.form = form.use('input', state, input);
|
||||||
|
|
||||||
vm.setListeners();
|
vm.setListeners();
|
||||||
vm.check();
|
vm.check();
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
ng-change="vm.check()" />
|
ng-change="vm.check()" />
|
||||||
|
|
||||||
<select class="form-control at-InputSelect-select" ng-model="config.state.value"
|
<select class="form-control at-InputSelect-select" ng-model="config.state.value"
|
||||||
tabindex="{{::tab}}" ng-attr-autofocus="{{ tab == 1 || undefined }}"
|
ng-attr-tabindex="{{ form.tabindex || undefined }}"
|
||||||
|
ng-attr-autofocus="{{ form.autofocus || undefined }}"
|
||||||
ng-disabled="form.disabled">
|
ng-disabled="form.disabled">
|
||||||
<optgroup ng-repeat="group in config.data" label="{{::group.category | uppercase }}">
|
<optgroup ng-repeat="group in config.data" label="{{::group.category | uppercase }}">
|
||||||
<option ng-repeat="item in group.data" value="{{ item.name }}">
|
<option ng-repeat="item in group.data" value="{{ item.name }}">
|
||||||
|
|||||||
@@ -23,10 +23,6 @@ function AtInputTextController () {
|
|||||||
state = scope.config.state;
|
state = scope.config.state;
|
||||||
state.required = scope.config.options.required;
|
state.required = scope.config.options.required;
|
||||||
|
|
||||||
if (scope.tab === '1') {
|
|
||||||
input.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
state.isValid = state.isValid || false;
|
state.isValid = state.isValid || false;
|
||||||
state.message = state.message || '';
|
state.message = state.message || '';
|
||||||
state.required = state.required || false;
|
state.required = state.required || false;
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
<div class="form-group at-u-flat">
|
<div class="form-group at-u-flat">
|
||||||
<at-input-label config="config"></at-input-label>
|
<at-input-label config="config"></at-input-label>
|
||||||
<input type="text" class="form-control at-Input" ng-model="config.state.value"
|
<input type="text" class="form-control at-Input" ng-model="config.state.value"
|
||||||
ng-attr-autofocus="{{ tab == 1 || undefined }}"
|
ng-attr-autofocus="{{ form.autofocus || undefined }}"
|
||||||
ng-attr-maxlength="{{ config.options.max_length || undefined }}"
|
ng-attr-maxlength="{{ config.options.max_length || undefined }}"
|
||||||
tabindex="{{::tab}}" placeholder="{{::config.placeholder}}"
|
tabindex="{{ form.tabindex || undefined }}"
|
||||||
|
placeholder="{{::config.placeholder}}"
|
||||||
ng-change="vm.check()" ng-disabled="form.disabled" />
|
ng-change="vm.check()" ng-disabled="form.disabled" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,30 +1,43 @@
|
|||||||
function categorizeByKind () {
|
|
||||||
let group = {};
|
|
||||||
|
|
||||||
this.model.data.results.forEach(result => {
|
|
||||||
group[result.kind] = group[result.kind] || [];
|
|
||||||
group[result.kind].push(result);
|
|
||||||
});
|
|
||||||
|
|
||||||
return Object.keys(group).map(category => ({
|
|
||||||
data: group[category],
|
|
||||||
category
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTypeFromName (name) {
|
|
||||||
let type = this.model.data.results.filter(result => result.name === name);
|
|
||||||
|
|
||||||
return type.length ? type[0] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function CredentialType (BaseModel) {
|
function CredentialType (BaseModel) {
|
||||||
Object.assign(this, BaseModel());
|
Object.assign(this, BaseModel());
|
||||||
|
|
||||||
this.path = this.normalizePath('credential_types');
|
this.path = this.normalizePath('credential_types');
|
||||||
|
|
||||||
this.categorizeByKind = categorizeByKind;
|
this.categorizeByKind = () => {
|
||||||
this.getTypeFromName = getTypeFromName;
|
let group = {};
|
||||||
|
|
||||||
|
this.model.data.results.forEach(result => {
|
||||||
|
group[result.kind] = group[result.kind] || [];
|
||||||
|
group[result.kind].push(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.keys(group).map(category => ({
|
||||||
|
data: group[category],
|
||||||
|
category
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getTypeFromName = name => {
|
||||||
|
let type = this.model.data.results.filter(result => result.name === name);
|
||||||
|
|
||||||
|
if (!type.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.mergeInputProperties(type[0]);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.mergeInputProperties = type => {
|
||||||
|
return type.inputs.fields.map(field => {
|
||||||
|
if (!type.inputs.required || type.inputs.required.indexOf(field.id) !== -1) {
|
||||||
|
field.required = false;
|
||||||
|
} else {
|
||||||
|
field.required = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return field;
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
CredentialType.$inject = ['BaseModel'];
|
CredentialType.$inject = ['BaseModel'];
|
||||||
|
|||||||
Reference in New Issue
Block a user