mirror of
https://github.com/ansible/awx.git
synced 2026-03-18 17:37:30 -02:30
add input source prompting and plugin testing
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
/* eslint camelcase: 0 */
|
||||||
|
/* eslint arrow-body-style: 0 */
|
||||||
function AddCredentialsController (
|
function AddCredentialsController (
|
||||||
models,
|
models,
|
||||||
$state,
|
$state,
|
||||||
@@ -6,7 +8,9 @@ function AddCredentialsController (
|
|||||||
componentsStrings,
|
componentsStrings,
|
||||||
ConfigService,
|
ConfigService,
|
||||||
ngToast,
|
ngToast,
|
||||||
$filter
|
Wait,
|
||||||
|
$filter,
|
||||||
|
CredentialType,
|
||||||
) {
|
) {
|
||||||
const vm = this || {};
|
const vm = this || {};
|
||||||
|
|
||||||
@@ -40,6 +44,44 @@ function AddCredentialsController (
|
|||||||
vm.form.credential_type._placeholder = strings.get('inputs.CREDENTIAL_TYPE_PLACEHOLDER');
|
vm.form.credential_type._placeholder = strings.get('inputs.CREDENTIAL_TYPE_PLACEHOLDER');
|
||||||
vm.isTestable = credentialType.get('kind') === 'external';
|
vm.isTestable = credentialType.get('kind') === 'external';
|
||||||
|
|
||||||
|
vm.inputSources = {
|
||||||
|
field: null,
|
||||||
|
credentialId: null,
|
||||||
|
credentialTypeId: null,
|
||||||
|
credentialTypeName: null,
|
||||||
|
tabs: {
|
||||||
|
credential: {
|
||||||
|
_active: true,
|
||||||
|
_disabled: false,
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
_active: false,
|
||||||
|
_disabled: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
metadata: {},
|
||||||
|
form: {
|
||||||
|
inputs: {
|
||||||
|
_get: () => vm.inputSources.metadata,
|
||||||
|
_reference: 'vm.form.inputs',
|
||||||
|
_key: 'inputs',
|
||||||
|
_source: { _value: {} },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
items: [],
|
||||||
|
};
|
||||||
|
vm.externalTest = {
|
||||||
|
metadata: null,
|
||||||
|
form: {
|
||||||
|
inputs: {
|
||||||
|
_get: () => vm.externalTest.metadata,
|
||||||
|
_reference: 'vm.form.inputs',
|
||||||
|
_key: 'inputs',
|
||||||
|
_source: { _value: {} },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const gceFileInputSchema = {
|
const gceFileInputSchema = {
|
||||||
id: 'gce_service_account_key',
|
id: 'gce_service_account_key',
|
||||||
type: 'file',
|
type: 'file',
|
||||||
@@ -50,10 +92,10 @@ function AddCredentialsController (
|
|||||||
let gceFileInputPreEditValues;
|
let gceFileInputPreEditValues;
|
||||||
|
|
||||||
vm.form.inputs = {
|
vm.form.inputs = {
|
||||||
_get: () => {
|
_get: ({ getSubmitData }) => {
|
||||||
credentialType.mergeInputProperties();
|
credentialType.mergeInputProperties();
|
||||||
|
|
||||||
const fields = credentialType.get('inputs.fields');
|
let fields = credentialType.get('inputs.fields');
|
||||||
|
|
||||||
if (credentialType.get('name') === 'Google Compute Engine') {
|
if (credentialType.get('name') === 'Google Compute Engine') {
|
||||||
fields.splice(2, 0, gceFileInputSchema);
|
fields.splice(2, 0, gceFileInputSchema);
|
||||||
@@ -64,55 +106,196 @@ function AddCredentialsController (
|
|||||||
become._isDynamic = true;
|
become._isDynamic = true;
|
||||||
become._choices = Array.from(apiConfig.become_methods, method => method[0]);
|
become._choices = Array.from(apiConfig.become_methods, method => method[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.isTestable = credentialType.get('kind') === 'external';
|
vm.isTestable = credentialType.get('kind') === 'external';
|
||||||
|
vm.getSubmitData = getSubmitData;
|
||||||
|
|
||||||
|
fields = fields.map((field) => {
|
||||||
|
if (credentialType.get('kind') !== 'external') {
|
||||||
|
field.tagMode = true;
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
});
|
||||||
|
|
||||||
return fields;
|
return fields;
|
||||||
},
|
},
|
||||||
|
_onRemoveTag ({ id }) {
|
||||||
|
vm.onInputSourceClear(id);
|
||||||
|
},
|
||||||
|
_onInputLookup ({ id }) {
|
||||||
|
vm.onInputSourceOpen(id);
|
||||||
|
},
|
||||||
_source: vm.form.credential_type,
|
_source: vm.form.credential_type,
|
||||||
_reference: 'vm.form.inputs',
|
_reference: 'vm.form.inputs',
|
||||||
_key: 'inputs'
|
_key: 'inputs'
|
||||||
};
|
};
|
||||||
|
|
||||||
vm.form.secondary = ({ inputs }) => {
|
vm.onInputSourceClear = (field) => {
|
||||||
const name = $filter('sanitize')(credentialType.get('name'));
|
vm.form[field].tagMode = true;
|
||||||
const endpoint = `${credentialType.get('id')}/test/`;
|
vm.form[field].asTag = false;
|
||||||
|
};
|
||||||
|
|
||||||
return credentialType.http.post({ url: endpoint, data: { inputs }, replace: false })
|
vm.setTab = (name) => {
|
||||||
|
const metaIsActive = name === 'metadata';
|
||||||
|
vm.inputSources.tabs.credential._active = !metaIsActive;
|
||||||
|
vm.inputSources.tabs.credential._disabled = false;
|
||||||
|
vm.inputSources.tabs.metadata._active = metaIsActive;
|
||||||
|
vm.inputSources.tabs.metadata._disabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.unsetTabs = () => {
|
||||||
|
vm.inputSources.tabs.credential._active = false;
|
||||||
|
vm.inputSources.tabs.credential._disabled = false;
|
||||||
|
vm.inputSources.tabs.metadata._active = false;
|
||||||
|
vm.inputSources.tabs.metadata._disabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceOpen = (field) => {
|
||||||
|
vm.inputSources.field = field;
|
||||||
|
vm.setTab('credential');
|
||||||
|
const sourceItem = vm.inputSources.items
|
||||||
|
.find(({ input_field_name }) => input_field_name === field);
|
||||||
|
if (sourceItem) {
|
||||||
|
const { source_credential, summary_fields } = sourceItem;
|
||||||
|
const { source_credential: { credential_type_id } } = summary_fields;
|
||||||
|
vm.inputSources.credentialId = source_credential;
|
||||||
|
vm.inputSources.credentialTypeId = credential_type_id;
|
||||||
|
vm.inputSources._value = credential_type_id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceClose = () => {
|
||||||
|
vm.inputSources.field = null;
|
||||||
|
vm.inputSources.metadata = null;
|
||||||
|
vm.unsetTabs();
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceNext = () => {
|
||||||
|
const { field, credentialId, credentialTypeId } = vm.inputSources;
|
||||||
|
Wait('start');
|
||||||
|
new CredentialType('get', credentialTypeId)
|
||||||
|
.then(model => {
|
||||||
|
model.mergeInputProperties('metadata');
|
||||||
|
vm.inputSources.metadata = model.get('inputs.metadata');
|
||||||
|
vm.inputSources.credentialTypeName = model.get('name');
|
||||||
|
const [metavals] = vm.inputSources.items
|
||||||
|
.filter(({ input_field_name }) => input_field_name === field)
|
||||||
|
.filter(({ source_credential }) => source_credential === credentialId)
|
||||||
|
.map(({ metadata }) => metadata);
|
||||||
|
Object.keys(metavals || {}).forEach(key => {
|
||||||
|
const obj = vm.inputSources.metadata.find(o => o.id === key);
|
||||||
|
if (obj) obj._value = metavals[key];
|
||||||
|
});
|
||||||
|
vm.setTab('metadata');
|
||||||
|
})
|
||||||
|
.finally(() => Wait('stop'));
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceSelect = () => {
|
||||||
|
const { field, credentialId } = vm.inputSources;
|
||||||
|
vm.inputSources.items = vm.inputSources.items
|
||||||
|
.filter(({ input_field_name }) => input_field_name !== field)
|
||||||
|
.concat([{
|
||||||
|
input_field_name: field,
|
||||||
|
source_credential: credentialId,
|
||||||
|
target_credential: credential.get('id'),
|
||||||
|
}]);
|
||||||
|
vm.inputSources.field = null;
|
||||||
|
vm.inputSources.metadata = null;
|
||||||
|
vm.unsetTabs();
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceTabSelect = (name) => {
|
||||||
|
if (name === 'metadata') {
|
||||||
|
vm.onInputSourceNext();
|
||||||
|
} else {
|
||||||
|
vm.setTab('credential');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceRowClick = ({ id, credential_type }) => {
|
||||||
|
vm.inputSources.credentialId = id;
|
||||||
|
vm.inputSources.credentialTypeId = credential_type;
|
||||||
|
vm.inputSources._value = credential_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceTest = () => {
|
||||||
|
const metadata = Object.assign({}, ...vm.inputSources.form.inputs._group
|
||||||
|
.filter(({ _value }) => _value !== undefined)
|
||||||
|
.map(({ id, _value }) => ({ [id]: _value })));
|
||||||
|
const name = $filter('sanitize')(vm.inputSources.credentialTypeName);
|
||||||
|
const endpoint = `${vm.inputSources.credentialId}/test/`;
|
||||||
|
|
||||||
|
return vm.runTest({ name, model: credential, endpoint, data: { metadata } });
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onExternalTestClick = () => {
|
||||||
|
credentialType.mergeInputProperties('metadata');
|
||||||
|
vm.externalTest.metadata = credentialType.get('inputs.metadata');
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onExternalTestClose = () => {
|
||||||
|
vm.externalTest.metadata = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onExternalTest = () => {
|
||||||
|
const name = $filter('sanitize')(credentialType.get('name'));
|
||||||
|
const { inputs } = vm.getSubmitData();
|
||||||
|
const metadata = Object.assign({}, ...vm.externalTest.form.inputs._group
|
||||||
|
.filter(({ _value }) => _value !== undefined)
|
||||||
|
.map(({ id, _value }) => ({ [id]: _value })));
|
||||||
|
|
||||||
|
let model;
|
||||||
|
if (credential.get('credential_type') !== credentialType.get('id')) {
|
||||||
|
model = credentialType;
|
||||||
|
} else {
|
||||||
|
model = credential;
|
||||||
|
}
|
||||||
|
|
||||||
|
const endpoint = `${model.get('id')}/test/`;
|
||||||
|
return vm.runTest({ name, model, endpoint, data: { inputs, metadata } });
|
||||||
|
};
|
||||||
|
vm.form.secondary = vm.onExternalTestClick;
|
||||||
|
|
||||||
|
vm.runTest = ({ name, model, endpoint, data: { inputs, metadata } }) => {
|
||||||
|
return model.http.post({ url: endpoint, data: { inputs, metadata }, replace: false })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ngToast.success({
|
ngToast.success({
|
||||||
content: `
|
content: vm.buildTestNotificationContent({
|
||||||
<div class="Toast-wrapper">
|
name,
|
||||||
<div class="Toast-icon">
|
icon: 'fa-check-circle',
|
||||||
<i class="fa fa-check-circle Toast-successIcon"></i>
|
msg: strings.get('edit.TEST_PASSED'),
|
||||||
</div>
|
}),
|
||||||
<div>
|
|
||||||
<b>${name}:</b> ${strings.get('edit.TEST_PASSED')}
|
|
||||||
</div>
|
|
||||||
</div>`,
|
|
||||||
dismissButton: false,
|
dismissButton: false,
|
||||||
dismissOnTimeout: true
|
dismissOnTimeout: true
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(({ data }) => {
|
.catch(({ data }) => {
|
||||||
const msg = data.inputs ? `${$filter('sanitize')(data.inputs)}` : strings.get('edit.TEST_FAILED');
|
const msg = data.inputs
|
||||||
|
? `${$filter('sanitize')(data.inputs)}`
|
||||||
|
: strings.get('edit.TEST_FAILED');
|
||||||
ngToast.danger({
|
ngToast.danger({
|
||||||
content: `
|
content: vm.buildTestNotificationContent({
|
||||||
<div class="Toast-wrapper">
|
name,
|
||||||
<div class="Toast-icon">
|
msg,
|
||||||
<i class="fa fa-exclamation-triangle Toast-successIcon"></i>
|
icon: 'fa-exclamation-triangle'
|
||||||
</div>
|
}),
|
||||||
<div>
|
|
||||||
<b>${name}:</b> ${msg}
|
|
||||||
</div>
|
|
||||||
</div>`,
|
|
||||||
dismissButton: false,
|
dismissButton: false,
|
||||||
dismissOnTimeout: true
|
dismissOnTimeout: true
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vm.buildTestNotificationContent = ({ name, msg, icon }) => (
|
||||||
|
`<div class="Toast-wrapper">
|
||||||
|
<div class="Toast-icon">
|
||||||
|
<i class="fa ${icon} Toast-successIcon"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b>${name}:</b> ${msg}
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
);
|
||||||
|
|
||||||
vm.form.save = data => {
|
vm.form.save = data => {
|
||||||
data.user = me.get('id');
|
data.user = me.get('id');
|
||||||
|
|
||||||
@@ -195,7 +378,9 @@ AddCredentialsController.$inject = [
|
|||||||
'ComponentsStrings',
|
'ComponentsStrings',
|
||||||
'ConfigService',
|
'ConfigService',
|
||||||
'ngToast',
|
'ngToast',
|
||||||
'$filter'
|
'Wait',
|
||||||
|
'$filter',
|
||||||
|
'CredentialTypeModel',
|
||||||
];
|
];
|
||||||
|
|
||||||
export default AddCredentialsController;
|
export default AddCredentialsController;
|
||||||
|
|||||||
@@ -43,5 +43,22 @@
|
|||||||
<div class="at-CredentialsPermissions" ui-view="related"></div>
|
<div class="at-CredentialsPermissions" ui-view="related"></div>
|
||||||
</at-panel-body>
|
</at-panel-body>
|
||||||
</at-panel>
|
</at-panel>
|
||||||
|
<at-input-source-lookup
|
||||||
|
ng-if="vm.inputSources.field"
|
||||||
|
selected-id="vm.inputSources.credentialId"
|
||||||
|
tabs="vm.inputSources.tabs"
|
||||||
|
form="vm.inputSources.form"
|
||||||
|
on-close="vm.onInputSourceClose"
|
||||||
|
on-next="vm.onInputSourceNext"
|
||||||
|
on-select="vm.onInputSourceSelect"
|
||||||
|
on-tab-select="vm.onInputSourceTabSelect"
|
||||||
|
on-row-click="vm.onInputSourceRowClick"
|
||||||
|
on-test="vm.onInputSourceTest"
|
||||||
|
/>
|
||||||
|
<at-external-credential-test
|
||||||
|
ng-if="vm.externalTest.metadata"
|
||||||
|
on-close="vm.onExternalTestClose"
|
||||||
|
on-submit="vm.onExternalTest"
|
||||||
|
form="vm.externalTest.form"
|
||||||
|
/>
|
||||||
<div ng-if="$state.current.name.includes('permissions.add')" ui-view="modal"></div>
|
<div ng-if="$state.current.name.includes('permissions.add')" ui-view="modal"></div>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
/* eslint camelcase: 0 */
|
||||||
|
/* eslint arrow-body-style: 0 */
|
||||||
function EditCredentialsController (
|
function EditCredentialsController (
|
||||||
models,
|
models,
|
||||||
$state,
|
$state,
|
||||||
@@ -8,10 +10,16 @@ function EditCredentialsController (
|
|||||||
ngToast,
|
ngToast,
|
||||||
Wait,
|
Wait,
|
||||||
$filter,
|
$filter,
|
||||||
|
CredentialType,
|
||||||
) {
|
) {
|
||||||
const vm = this || {};
|
const vm = this || {};
|
||||||
|
const {
|
||||||
const { me, credential, credentialType, organization, isOrgCredAdmin } = models;
|
me,
|
||||||
|
credential,
|
||||||
|
credentialType,
|
||||||
|
organization,
|
||||||
|
isOrgCredAdmin,
|
||||||
|
} = models;
|
||||||
|
|
||||||
const omit = ['user', 'team', 'inputs'];
|
const omit = ['user', 'team', 'inputs'];
|
||||||
const isEditable = credential.isEditable();
|
const isEditable = credential.isEditable();
|
||||||
@@ -88,6 +96,44 @@ function EditCredentialsController (
|
|||||||
vm.form.credential_type._placeholder = strings.get('inputs.CREDENTIAL_TYPE_PLACEHOLDER');
|
vm.form.credential_type._placeholder = strings.get('inputs.CREDENTIAL_TYPE_PLACEHOLDER');
|
||||||
vm.isTestable = (isEditable && credentialType.get('kind') === 'external');
|
vm.isTestable = (isEditable && credentialType.get('kind') === 'external');
|
||||||
|
|
||||||
|
vm.inputSources = {
|
||||||
|
field: null,
|
||||||
|
credentialId: null,
|
||||||
|
credentialTypeId: null,
|
||||||
|
credentialTypeName: null,
|
||||||
|
tabs: {
|
||||||
|
credential: {
|
||||||
|
_active: true,
|
||||||
|
_disabled: false,
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
_active: false,
|
||||||
|
_disabled: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
metadata: {},
|
||||||
|
form: {
|
||||||
|
inputs: {
|
||||||
|
_get: () => vm.inputSources.metadata,
|
||||||
|
_reference: 'vm.form.inputs',
|
||||||
|
_key: 'inputs',
|
||||||
|
_source: { _value: {} },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
items: credential.get('related.input_sources.results'),
|
||||||
|
};
|
||||||
|
vm.externalTest = {
|
||||||
|
metadata: null,
|
||||||
|
form: {
|
||||||
|
inputs: {
|
||||||
|
_get: () => vm.externalTest.metadata,
|
||||||
|
_reference: 'vm.form.inputs',
|
||||||
|
_key: 'inputs',
|
||||||
|
_source: { _value: {} },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const gceFileInputSchema = {
|
const gceFileInputSchema = {
|
||||||
id: 'gce_service_account_key',
|
id: 'gce_service_account_key',
|
||||||
type: 'file',
|
type: 'file',
|
||||||
@@ -98,7 +144,7 @@ function EditCredentialsController (
|
|||||||
let gceFileInputPreEditValues;
|
let gceFileInputPreEditValues;
|
||||||
|
|
||||||
vm.form.inputs = {
|
vm.form.inputs = {
|
||||||
_get () {
|
_get ({ getSubmitData }) {
|
||||||
let fields;
|
let fields;
|
||||||
|
|
||||||
credentialType.mergeInputProperties();
|
credentialType.mergeInputProperties();
|
||||||
@@ -128,54 +174,199 @@ function EditCredentialsController (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fields = fields.map((field) => {
|
||||||
|
if (isEditable && credentialType.get('kind') !== 'external') {
|
||||||
|
field.tagMode = true;
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
});
|
||||||
|
|
||||||
vm.isTestable = (isEditable && credentialType.get('kind') === 'external');
|
vm.isTestable = (isEditable && credentialType.get('kind') === 'external');
|
||||||
|
vm.getSubmitData = getSubmitData;
|
||||||
|
|
||||||
return fields;
|
return fields;
|
||||||
},
|
},
|
||||||
|
_onRemoveTag ({ id }) {
|
||||||
|
vm.onInputSourceClear(id);
|
||||||
|
},
|
||||||
|
_onInputLookup ({ id }) {
|
||||||
|
vm.onInputSourceOpen(id);
|
||||||
|
},
|
||||||
_source: vm.form.credential_type,
|
_source: vm.form.credential_type,
|
||||||
_reference: 'vm.form.inputs',
|
_reference: 'vm.form.inputs',
|
||||||
_key: 'inputs'
|
_key: 'inputs',
|
||||||
|
border: true,
|
||||||
|
title: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
vm.form.secondary = ({ inputs }) => {
|
vm.onInputSourceClear = (field) => {
|
||||||
const name = $filter('sanitize')(credentialType.get('name'));
|
vm.form[field].tagMode = true;
|
||||||
const endpoint = `${credential.get('id')}/test/`;
|
vm.form[field].asTag = false;
|
||||||
|
};
|
||||||
|
|
||||||
return credential.http.post({ url: endpoint, data: { inputs }, replace: false })
|
vm.setTab = (name) => {
|
||||||
|
const metaIsActive = name === 'metadata';
|
||||||
|
vm.inputSources.tabs.credential._active = !metaIsActive;
|
||||||
|
vm.inputSources.tabs.credential._disabled = false;
|
||||||
|
vm.inputSources.tabs.metadata._active = metaIsActive;
|
||||||
|
vm.inputSources.tabs.metadata._disabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.unsetTabs = () => {
|
||||||
|
vm.inputSources.tabs.credential._active = false;
|
||||||
|
vm.inputSources.tabs.credential._disabled = false;
|
||||||
|
vm.inputSources.tabs.metadata._active = false;
|
||||||
|
vm.inputSources.tabs.metadata._disabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceOpen = (field) => {
|
||||||
|
vm.inputSources.field = field;
|
||||||
|
vm.setTab('credential');
|
||||||
|
const sourceItem = vm.inputSources.items
|
||||||
|
.find(({ input_field_name }) => input_field_name === field);
|
||||||
|
if (sourceItem) {
|
||||||
|
const { source_credential, summary_fields } = sourceItem;
|
||||||
|
const { source_credential: { credential_type_id } } = summary_fields;
|
||||||
|
vm.inputSources.credentialId = source_credential;
|
||||||
|
vm.inputSources.credentialTypeId = credential_type_id;
|
||||||
|
vm.inputSources._value = credential_type_id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceClose = () => {
|
||||||
|
vm.inputSources.field = null;
|
||||||
|
vm.inputSources.metadata = null;
|
||||||
|
vm.unsetTabs();
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceNext = () => {
|
||||||
|
const { field, credentialId, credentialTypeId } = vm.inputSources;
|
||||||
|
Wait('start');
|
||||||
|
new CredentialType('get', credentialTypeId)
|
||||||
|
.then(model => {
|
||||||
|
model.mergeInputProperties('metadata');
|
||||||
|
vm.inputSources.metadata = model.get('inputs.metadata');
|
||||||
|
vm.inputSources.credentialTypeName = model.get('name');
|
||||||
|
const [metavals] = vm.inputSources.items
|
||||||
|
.filter(({ input_field_name }) => input_field_name === field)
|
||||||
|
.filter(({ source_credential }) => source_credential === credentialId)
|
||||||
|
.map(({ metadata }) => metadata);
|
||||||
|
Object.keys(metavals || {}).forEach(key => {
|
||||||
|
const obj = vm.inputSources.metadata.find(o => o.id === key);
|
||||||
|
if (obj) obj._value = metavals[key];
|
||||||
|
});
|
||||||
|
vm.setTab('metadata');
|
||||||
|
})
|
||||||
|
.finally(() => Wait('stop'));
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceSelect = () => {
|
||||||
|
const { field, credentialId } = vm.inputSources;
|
||||||
|
vm.inputSources.items = vm.inputSources.items
|
||||||
|
.filter(({ input_field_name }) => input_field_name !== field)
|
||||||
|
.concat([{
|
||||||
|
input_field_name: field,
|
||||||
|
source_credential: credentialId,
|
||||||
|
target_credential: credential.get('id'),
|
||||||
|
}]);
|
||||||
|
vm.inputSources.field = null;
|
||||||
|
vm.inputSources.metadata = null;
|
||||||
|
vm.unsetTabs();
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceTabSelect = (name) => {
|
||||||
|
if (name === 'metadata') {
|
||||||
|
vm.onInputSourceNext();
|
||||||
|
} else {
|
||||||
|
vm.setTab('credential');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceRowClick = ({ id, credential_type }) => {
|
||||||
|
vm.inputSources.credentialId = id;
|
||||||
|
vm.inputSources.credentialTypeId = credential_type;
|
||||||
|
vm.inputSources._value = credential_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onInputSourceTest = () => {
|
||||||
|
const metadata = Object.assign({}, ...vm.inputSources.form.inputs._group
|
||||||
|
.filter(({ _value }) => _value !== undefined)
|
||||||
|
.map(({ id, _value }) => ({ [id]: _value })));
|
||||||
|
const name = $filter('sanitize')(vm.inputSources.credentialTypeName);
|
||||||
|
const endpoint = `${vm.inputSources.credentialId}/test/`;
|
||||||
|
|
||||||
|
return vm.runTest({ name, model: credential, endpoint, data: { metadata } });
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onExternalTestClick = () => {
|
||||||
|
credentialType.mergeInputProperties('metadata');
|
||||||
|
vm.externalTest.metadata = credentialType.get('inputs.metadata');
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onExternalTestClose = () => {
|
||||||
|
vm.externalTest.metadata = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onExternalTest = () => {
|
||||||
|
const name = $filter('sanitize')(credentialType.get('name'));
|
||||||
|
const { inputs } = vm.getSubmitData();
|
||||||
|
const metadata = Object.assign({}, ...vm.externalTest.form.inputs._group
|
||||||
|
.filter(({ _value }) => _value !== undefined)
|
||||||
|
.map(({ id, _value }) => ({ [id]: _value })));
|
||||||
|
|
||||||
|
let model;
|
||||||
|
if (credential.get('credential_type') !== credentialType.get('id')) {
|
||||||
|
model = credentialType;
|
||||||
|
} else {
|
||||||
|
model = credential;
|
||||||
|
}
|
||||||
|
|
||||||
|
const endpoint = `${model.get('id')}/test/`;
|
||||||
|
return vm.runTest({ name, model, endpoint, data: { inputs, metadata } });
|
||||||
|
};
|
||||||
|
vm.form.secondary = vm.onExternalTestClick;
|
||||||
|
|
||||||
|
vm.runTest = ({ name, model, endpoint, data: { inputs, metadata } }) => {
|
||||||
|
return model.http.post({ url: endpoint, data: { inputs, metadata }, replace: false })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
ngToast.success({
|
ngToast.success({
|
||||||
content: `
|
content: vm.buildTestNotificationContent({
|
||||||
<div class="Toast-wrapper">
|
name,
|
||||||
<div class="Toast-icon">
|
icon: 'fa-check-circle',
|
||||||
<i class="fa fa-check-circle Toast-successIcon"></i>
|
msg: strings.get('edit.TEST_PASSED'),
|
||||||
</div>
|
}),
|
||||||
<div>
|
|
||||||
<b>${name}:</b> ${strings.get('edit.TEST_PASSED')}
|
|
||||||
</div>
|
|
||||||
</div>`,
|
|
||||||
dismissButton: false,
|
dismissButton: false,
|
||||||
dismissOnTimeout: true
|
dismissOnTimeout: true
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(({ data }) => {
|
.catch(({ data }) => {
|
||||||
const msg = data.inputs ? `${$filter('sanitize')(data.inputs)}` : strings.get('edit.TEST_FAILED');
|
const msg = data.inputs
|
||||||
|
? `${$filter('sanitize')(data.inputs)}`
|
||||||
|
: strings.get('edit.TEST_FAILED');
|
||||||
ngToast.danger({
|
ngToast.danger({
|
||||||
content: `
|
content: vm.buildTestNotificationContent({
|
||||||
<div class="Toast-wrapper">
|
name,
|
||||||
<div class="Toast-icon">
|
msg,
|
||||||
<i class="fa fa-exclamation-triangle Toast-successIcon"></i>
|
icon: 'fa-exclamation-triangle'
|
||||||
</div>
|
}),
|
||||||
<div>
|
|
||||||
<b>${name}:</b> ${msg}
|
|
||||||
</div>
|
|
||||||
</div>`,
|
|
||||||
dismissButton: false,
|
dismissButton: false,
|
||||||
dismissOnTimeout: true
|
dismissOnTimeout: true
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vm.buildTestNotificationContent = ({ name, msg, icon }) => (
|
||||||
|
`<div class="Toast-wrapper">
|
||||||
|
<div class="Toast-icon">
|
||||||
|
<i class="fa ${icon} Toast-successIcon"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<b>${name}:</b> ${msg}
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If a credential's `credential_type` is changed while editing, the inputs associated with
|
* If a credential's `credential_type` is changed while editing, the inputs associated with
|
||||||
* the old type need to be cleared before saving the inputs associated with the new type.
|
* the old type need to be cleared before saving the inputs associated with the new type.
|
||||||
@@ -258,6 +449,7 @@ EditCredentialsController.$inject = [
|
|||||||
'ngToast',
|
'ngToast',
|
||||||
'Wait',
|
'Wait',
|
||||||
'$filter',
|
'$filter',
|
||||||
|
'CredentialTypeModel',
|
||||||
];
|
];
|
||||||
|
|
||||||
export default EditCredentialsController;
|
export default EditCredentialsController;
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
const templateUrl = require('~features/credentials/external-test.partial.html');
|
||||||
|
|
||||||
|
function ExternalTestModalController ($scope, $element, strings) {
|
||||||
|
const vm = this || {};
|
||||||
|
let overlay;
|
||||||
|
|
||||||
|
vm.strings = strings;
|
||||||
|
vm.title = 'Test External Credential';
|
||||||
|
|
||||||
|
vm.$onInit = () => {
|
||||||
|
const [el] = $element;
|
||||||
|
overlay = el.querySelector('#external-test-modal');
|
||||||
|
vm.show();
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.show = () => {
|
||||||
|
overlay.style.display = 'block';
|
||||||
|
overlay.style.opacity = 1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalTestModalController.$inject = [
|
||||||
|
'$scope',
|
||||||
|
'$element',
|
||||||
|
'CredentialsStrings',
|
||||||
|
];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
templateUrl,
|
||||||
|
controller: ExternalTestModalController,
|
||||||
|
controllerAs: 'vm',
|
||||||
|
bindings: {
|
||||||
|
onClose: '=',
|
||||||
|
onSubmit: '=',
|
||||||
|
form: '=',
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<div id="external-test-modal" class="modal at-Modal" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content at-Modal-window">
|
||||||
|
<div class="Modal-header">
|
||||||
|
<div class="Modal-title">
|
||||||
|
<div class="at-Modal-heading">
|
||||||
|
<h4 class="modal-title at-Modal-title">{{ vm.title }}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="Modal-exitHolder">
|
||||||
|
<div class="at-Modal-dismiss">
|
||||||
|
<i class="fa fa-lg fa-times-circle" ng-click="vm.onClose()"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<at-form state="vm.form" autocomplete="off" id="external_test_form">
|
||||||
|
<at-input-group col="12" tab="20" state="vm.form.inputs" form-id="external_test">
|
||||||
|
TITLE
|
||||||
|
</at-input-group>
|
||||||
|
</at-form>
|
||||||
|
<div >
|
||||||
|
<div class="Prompt-footer">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="Prompt-defaultButton"
|
||||||
|
ng-click="vm.onClose()"
|
||||||
|
>
|
||||||
|
{{:: vm.strings.get('CLOSE') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="Prompt-actionButton"
|
||||||
|
ng-click="vm.onSubmit()"
|
||||||
|
>
|
||||||
|
{{:: vm.strings.get('RUN') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -2,6 +2,8 @@ import LegacyCredentials from './legacy.credentials';
|
|||||||
import AddController from './add-credentials.controller';
|
import AddController from './add-credentials.controller';
|
||||||
import EditController from './edit-credentials.controller';
|
import EditController from './edit-credentials.controller';
|
||||||
import CredentialsStrings from './credentials.strings';
|
import CredentialsStrings from './credentials.strings';
|
||||||
|
import InputSourceLookupComponent from './input-source-lookup.component';
|
||||||
|
import ExternalTestComponent from './external-test.component';
|
||||||
|
|
||||||
const MODULE_NAME = 'at.features.credentials';
|
const MODULE_NAME = 'at.features.credentials';
|
||||||
|
|
||||||
@@ -40,7 +42,8 @@ function CredentialsResolve (
|
|||||||
|
|
||||||
const dependents = {
|
const dependents = {
|
||||||
credentialType: new CredentialType('get', typeId),
|
credentialType: new CredentialType('get', typeId),
|
||||||
organization: new Organization('get', orgId)
|
organization: new Organization('get', orgId),
|
||||||
|
credentialInputSources: models.credential.extend('GET', 'input_sources')
|
||||||
};
|
};
|
||||||
dependents.isOrgCredAdmin = dependents.organization.then((org) => org.search({ role_level: 'credential_admin_role' }));
|
dependents.isOrgCredAdmin = dependents.organization.then((org) => org.search({ role_level: 'credential_admin_role' }));
|
||||||
|
|
||||||
@@ -139,6 +142,8 @@ angular
|
|||||||
.controller('EditController', EditController)
|
.controller('EditController', EditController)
|
||||||
.service('LegacyCredentialsService', LegacyCredentials)
|
.service('LegacyCredentialsService', LegacyCredentials)
|
||||||
.service('CredentialsStrings', CredentialsStrings)
|
.service('CredentialsStrings', CredentialsStrings)
|
||||||
|
.component('atInputSourceLookup', InputSourceLookupComponent)
|
||||||
|
.component('atExternalCredentialTest', ExternalTestComponent)
|
||||||
.run(CredentialsRun);
|
.run(CredentialsRun);
|
||||||
|
|
||||||
export default MODULE_NAME;
|
export default MODULE_NAME;
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
const templateUrl = require('~features/credentials/input-source-lookup.partial.html');
|
||||||
|
|
||||||
|
function InputSourceLookupController ($scope, $element, $http, GetBasePath, qs, strings) {
|
||||||
|
const vm = this || {};
|
||||||
|
let overlay;
|
||||||
|
|
||||||
|
vm.strings = strings;
|
||||||
|
vm.name = 'credential';
|
||||||
|
vm.title = 'Set Input Source';
|
||||||
|
|
||||||
|
vm.$onInit = () => {
|
||||||
|
const [el] = $element;
|
||||||
|
overlay = el.querySelector('#input-source-lookup');
|
||||||
|
|
||||||
|
const defaultParams = {
|
||||||
|
order_by: 'name',
|
||||||
|
credential_type__kind: 'external',
|
||||||
|
page_size: 5
|
||||||
|
};
|
||||||
|
vm.setDefaultParams(defaultParams);
|
||||||
|
vm.setData({ results: [], count: 0 });
|
||||||
|
$http({ method: 'GET', url: GetBasePath(`${vm.name}s`), params: defaultParams })
|
||||||
|
.then(({ data }) => {
|
||||||
|
vm.setData(data);
|
||||||
|
vm.show();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.show = () => {
|
||||||
|
overlay.style.display = 'block';
|
||||||
|
overlay.style.opacity = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.close = () => {
|
||||||
|
vm.onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.next = () => {
|
||||||
|
vm.onNext();
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.select = () => {
|
||||||
|
vm.onSelect();
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.test = () => {
|
||||||
|
vm.onTest();
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.setData = ({ results, count }) => {
|
||||||
|
vm.dataset = { results, count };
|
||||||
|
vm.collection = vm.dataset.results;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.setDefaultParams = (params) => {
|
||||||
|
vm.list = { name: vm.name, iterator: vm.name };
|
||||||
|
vm.defaultParams = params;
|
||||||
|
vm.queryset = params;
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.toggle_row = (obj) => {
|
||||||
|
vm.onRowClick(obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.onCredentialTabClick = () => vm.onTabSelect('credential');
|
||||||
|
}
|
||||||
|
|
||||||
|
InputSourceLookupController.$inject = [
|
||||||
|
'$scope',
|
||||||
|
'$element',
|
||||||
|
'$http',
|
||||||
|
'GetBasePath',
|
||||||
|
'QuerySet',
|
||||||
|
'CredentialsStrings',
|
||||||
|
];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
templateUrl,
|
||||||
|
controller: InputSourceLookupController,
|
||||||
|
controllerAs: 'vm',
|
||||||
|
bindings: {
|
||||||
|
tabs: '=',
|
||||||
|
onClose: '=',
|
||||||
|
onNext: '=',
|
||||||
|
onSelect: '=',
|
||||||
|
onTabSelect: '=',
|
||||||
|
onRowClick: '=',
|
||||||
|
onTest: '=',
|
||||||
|
selectedId: '=',
|
||||||
|
form: '=',
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
<div id="input-source-lookup" class="modal at-Modal" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content at-Modal-window">
|
||||||
|
<div class="Modal-header">
|
||||||
|
<div class="Modal-title">
|
||||||
|
<div class="at-Modal-heading">
|
||||||
|
<h4 class="modal-title at-Modal-title">{{ vm.title }}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="Modal-exitHolder">
|
||||||
|
<div class="at-Modal-dismiss">
|
||||||
|
<i class="fa fa-lg fa-times-circle" ng-click="vm.close()"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- =================================================================================================== -->
|
||||||
|
<at-tab-group>
|
||||||
|
<at-tab
|
||||||
|
state="vm.tabs.credential"
|
||||||
|
ng-click="vm.onTabSelect('credential');"
|
||||||
|
>
|
||||||
|
CREDENTIAL
|
||||||
|
</at-tab>
|
||||||
|
<at-tab
|
||||||
|
state="vm.tabs.metadata"
|
||||||
|
ng-click="vm.onTabSelect('metadata');"
|
||||||
|
>
|
||||||
|
METADATA
|
||||||
|
</at-tab>
|
||||||
|
</at-tab-group>
|
||||||
|
<div></div>
|
||||||
|
<!-- =================================================================================================== -->
|
||||||
|
|
||||||
|
<div ng-if="vm.tabs.metadata._active">
|
||||||
|
<at-form state="vm.form" autocomplete="off" id="input_source_form">
|
||||||
|
<at-input-group col="12" tab="20" state="vm.form.inputs" form-id="input_source">
|
||||||
|
TITLE
|
||||||
|
</at-input-group>
|
||||||
|
</at-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-show="vm.tabs.credential._active">
|
||||||
|
<div ng-hide="vm.collection.length === 0 && (searchTags | isEmpty)">
|
||||||
|
<div style="min-height: 20px"></div>
|
||||||
|
<smart-search
|
||||||
|
django-model="{{ vm.name + 's' }}"
|
||||||
|
base-path="{{ vm.name + 's' }}"
|
||||||
|
iterator="{{ vm.list.iterator }}"
|
||||||
|
dataset="vm.dataset"
|
||||||
|
list="vm.list"
|
||||||
|
collection="vm.collection"
|
||||||
|
default-params="vm.defaultParams"
|
||||||
|
query-set="vm.queryset"
|
||||||
|
search-tags="searchTags">
|
||||||
|
</smart-search>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="row"
|
||||||
|
ng-show="vm.collection.length === 0 && !(searchTags | isEmpty)"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="col-lg-12 List-searchNoResults"
|
||||||
|
translate
|
||||||
|
>
|
||||||
|
No records matched your search.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="List-noItems"
|
||||||
|
ng-show="vm.collection.length === 0 && (searchTags | isEmpty)"
|
||||||
|
>
|
||||||
|
PLEASE ADD ITEMS TO THIS LIST
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="list-table-container"
|
||||||
|
ng-show="vm.collection.length > 0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
id="credential_input_source_table"
|
||||||
|
class="List-table"
|
||||||
|
is-extended="false"
|
||||||
|
>
|
||||||
|
<div class="List-lookupLayout List-tableHeaderRow">
|
||||||
|
<div></div>
|
||||||
|
<div class="d-flex h-100">
|
||||||
|
<div
|
||||||
|
base-path="{{ vm.name + 's' }}"
|
||||||
|
collection="vm.collection"
|
||||||
|
dataset="vm.dataset"
|
||||||
|
column-sort=""
|
||||||
|
column-field="name"
|
||||||
|
column-iterator="{{ vm.list.iterator }}"
|
||||||
|
column-label="Name"
|
||||||
|
column-custom-class="List-tableCell col-md-4 col-sm-9 col-xs-9"
|
||||||
|
query-set="vm.queryset"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
id="{{ obj.id }}"
|
||||||
|
class="List-lookupLayout List-tableRow"
|
||||||
|
ng-repeat="obj in vm.collection"
|
||||||
|
>
|
||||||
|
<div class="List-centerEnd select-column">
|
||||||
|
<input type="radio"
|
||||||
|
name="check_{{ vm.name }}_{{ obj.id }}"
|
||||||
|
ng-checked="obj.id === vm.selectedId"
|
||||||
|
ng-click="vm.toggle_row(obj)"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex h-100">
|
||||||
|
<div
|
||||||
|
class="List-tableCell name-column col-sm-12"
|
||||||
|
ng-click="vm.toggle_row(obj)"
|
||||||
|
>
|
||||||
|
{{ obj.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<paginate
|
||||||
|
base-path="{{ vm.name + 's' }}"
|
||||||
|
collection="vm.collection"
|
||||||
|
dataset="vm.dataset"
|
||||||
|
iterator="{{ vm.list.iterator }}"
|
||||||
|
query-set="vm.queryset"
|
||||||
|
hide-view-per-page="true"
|
||||||
|
>
|
||||||
|
</paginate>
|
||||||
|
</div>
|
||||||
|
<!-- ============================================================================================ -->
|
||||||
|
<div >
|
||||||
|
<div class="Prompt-footer">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="Prompt-infoButton"
|
||||||
|
ng-show="vm.tabs.metadata._active"
|
||||||
|
ng-click="vm.test()"
|
||||||
|
>
|
||||||
|
{{:: vm.strings.get('TEST') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="Prompt-defaultButton"
|
||||||
|
ng-click="vm.close()"
|
||||||
|
>
|
||||||
|
{{:: vm.strings.get('CANCEL') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="Prompt-actionButton"
|
||||||
|
ng-show="vm.tabs.credential._active"
|
||||||
|
ng-click="vm.next()"
|
||||||
|
>
|
||||||
|
{{:: vm.strings.get('NEXT') }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
ng-disabled="true"
|
||||||
|
type="button"
|
||||||
|
class="Prompt-actionButton"
|
||||||
|
ng-show="vm.tabs.metadata._active"
|
||||||
|
ng-click="vm.select()"
|
||||||
|
>
|
||||||
|
{{:: vm.strings.get('OK') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -87,13 +87,8 @@ function AtFormController (eventService, strings) {
|
|||||||
if (!vm.state.isValid) {
|
if (!vm.state.isValid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.state.disabled = true;
|
|
||||||
|
|
||||||
const data = vm.getSubmitData();
|
const data = vm.getSubmitData();
|
||||||
|
scope.state.secondary(data);
|
||||||
scope.state.secondary(data)
|
|
||||||
.finally(() => { vm.state.disabled = false; });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
vm.submit = () => {
|
vm.submit = () => {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ function AtInputGroupController ($scope, $compile) {
|
|||||||
|
|
||||||
state._value = source._value;
|
state._value = source._value;
|
||||||
|
|
||||||
const inputs = state._get(source._value);
|
const inputs = state._get(form);
|
||||||
const group = vm.createComponentConfigs(inputs);
|
const group = vm.createComponentConfigs(inputs);
|
||||||
|
|
||||||
vm.insert(group);
|
vm.insert(group);
|
||||||
@@ -66,7 +66,9 @@ function AtInputGroupController ($scope, $compile) {
|
|||||||
_element: vm.createComponent(input, i),
|
_element: vm.createComponent(input, i),
|
||||||
_key: 'inputs',
|
_key: 'inputs',
|
||||||
_group: true,
|
_group: true,
|
||||||
_groupIndex: i
|
_groupIndex: i,
|
||||||
|
_onInputLookup: state._onInputLookup,
|
||||||
|
_onRemoveTag: state._onRemoveTag,
|
||||||
}, input));
|
}, input));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -160,7 +162,6 @@ function AtInputGroupController ($scope, $compile) {
|
|||||||
</${input._component}>`);
|
</${input._component}>`);
|
||||||
|
|
||||||
$compile(component)(scope.$parent);
|
$compile(component)(scope.$parent);
|
||||||
|
|
||||||
return component;
|
return component;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div ng-show="state._group" class="col-sm-12 at-InputGroup">
|
<div ng-show="state._group" class="col-sm-12 at-InputGroup">
|
||||||
<div class="at-InputGroup-border"></div>
|
<div ng-if="state.border" class="at-InputGroup-border"></div>
|
||||||
<div class="at-InputGroup-inset">
|
<div class="at-InputGroup-inset">
|
||||||
<div class="row">
|
<div ng-if="state.title" class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<h4 class="at-InputGroup-title">
|
<h4 class="at-InputGroup-title">
|
||||||
<ng-transclude></ng-transclude>
|
<ng-transclude></ng-transclude>
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ function atInputTextLink (scope, element, attrs, controllers) {
|
|||||||
const inputController = controllers[1];
|
const inputController = controllers[1];
|
||||||
|
|
||||||
if (scope.tab === '1') {
|
if (scope.tab === '1') {
|
||||||
element.find('input')[0].focus();
|
const el = element.find('input')[0];
|
||||||
|
if (el) {
|
||||||
|
el.focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inputController.init(scope, element, formController);
|
inputController.init(scope, element, formController);
|
||||||
@@ -20,9 +23,15 @@ function AtInputTextController (baseInputController) {
|
|||||||
baseInputController.call(vm, 'input', _scope_, element, form);
|
baseInputController.call(vm, 'input', _scope_, element, form);
|
||||||
scope = _scope_;
|
scope = _scope_;
|
||||||
|
|
||||||
vm.check();
|
|
||||||
scope.$watch('state._value', () => vm.check());
|
scope.$watch('state._value', () => vm.check());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vm.onLookupClick = () => {
|
||||||
|
if (scope.state._onInputLookup) {
|
||||||
|
const { id, label, required, type } = scope.state;
|
||||||
|
scope.state._onInputLookup({ id, label, required, type });
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
AtInputTextController.$inject = ['BaseInputController'];
|
AtInputTextController.$inject = ['BaseInputController'];
|
||||||
|
|||||||
@@ -1,15 +1,40 @@
|
|||||||
<div class="col-sm-{{::col}} at-InputContainer">
|
<div class="col-sm-{{::col}} at-InputContainer">
|
||||||
<div class="form-group at-u-flat">
|
<div class="form-group at-u-flat">
|
||||||
<at-input-label></at-input-label>
|
<at-input-label></at-input-label>
|
||||||
|
<div ng-if="state.tagMode" class="input-group">
|
||||||
<input type="text" class="form-control at-Input"
|
<span class="input-group-btn input-group-prepend">
|
||||||
ng-class="{ 'at-Input--rejected': state._rejected }"
|
<button
|
||||||
ng-model="state._value"
|
class="btn at-ButtonHollow--default at-Input-button"
|
||||||
ng-attr-maxlength="{{ state.max_length || undefined }}"
|
ng-disabled="state._disabled || form.disabled"
|
||||||
ng-attr-tabindex="{{ tab || undefined }}"
|
ng-click="vm.onLookupClick()">
|
||||||
ng-attr-placeholder="{{::state._placeholder || undefined }}"
|
<i class="fa fa-search"></i>
|
||||||
ng-disabled="state._disabled || form.disabled" />
|
</button>
|
||||||
|
</span>
|
||||||
|
<span ng-if="state.asTag" class="form-control at-Input">
|
||||||
|
<at-tag
|
||||||
|
ng-show="state._value"
|
||||||
|
icon="external"
|
||||||
|
tag="state._value"
|
||||||
|
remove-tag="state._onRemoveTag(state)"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<input ng-if="!state.asTag" type="text" class="form-control at-Input"
|
||||||
|
ng-class="{ 'at-Input--rejected': state._rejected }"
|
||||||
|
ng-model="state._value"
|
||||||
|
ng-attr-maxlength="{{ state.max_length || undefined }}"
|
||||||
|
ng-attr-tabindex="{{ tab || undefined }}"
|
||||||
|
ng-attr-placeholder="{{::state._placeholder || undefined }}"
|
||||||
|
ng-disabled="state._disabled || form.disabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<input ng-if="!state.tagMode" type="text" class="form-control at-Input"
|
||||||
|
ng-class="{ 'at-Input--rejected': state._rejected }"
|
||||||
|
ng-model="state._value"
|
||||||
|
ng-attr-maxlength="{{ state.max_length || undefined }}"
|
||||||
|
ng-attr-tabindex="{{ tab || undefined }}"
|
||||||
|
ng-attr-placeholder="{{::state._placeholder || undefined }}"
|
||||||
|
ng-disabled="state._disabled || form.disabled"
|
||||||
|
/>
|
||||||
<at-input-message></at-input-message>
|
<at-input-message></at-input-message>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
ng-attr-disabled="{{ state._disabled || undefined }}"
|
ng-attr-disabled="{{ state._disabled || undefined }}"
|
||||||
ng-class="{ 'at-Tab--active': state._active, 'at-Tab--disabled': state._disabled }"
|
ng-class="{ 'at-Tab--active': state._active, 'at-Tab--disabled': state._disabled }"
|
||||||
ng-hide="{{ state._hide }}"
|
ng-hide="{{ state._hide }}"
|
||||||
ng-click="vm.go()">
|
ng-click="state._go && vm.go();">
|
||||||
<ng-transclude></ng-transclude>
|
<ng-transclude></ng-transclude>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -61,6 +61,10 @@
|
|||||||
&--vault:before {
|
&--vault:before {
|
||||||
content: '\f187';
|
content: '\f187';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&--external:before {
|
||||||
|
content: '\f14c'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.TagComponent-button {
|
.TagComponent-button {
|
||||||
|
|||||||
@@ -15,18 +15,18 @@ function categorizeByKind () {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeInputProperties () {
|
function mergeInputProperties (key = 'fields') {
|
||||||
if (!this.has('inputs.fields')) {
|
if (!this.has(`inputs.${key}`)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const required = this.get('inputs.required');
|
const required = this.get('inputs.required');
|
||||||
|
|
||||||
return this.get('inputs.fields').forEach((field, i) => {
|
return this.get(`inputs.${key}`).forEach((field, i) => {
|
||||||
if (!required || required.indexOf(field.id) === -1) {
|
if (!required || required.indexOf(field.id) === -1) {
|
||||||
this.set(`inputs.fields[${i}].required`, false);
|
this.set(`inputs.${key}[${i}].required`, false);
|
||||||
} else {
|
} else {
|
||||||
this.set(`inputs.fields[${i}].required`, true);
|
this.set(`inputs.${key}[${i}].required`, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ function BaseStringService (namespace) {
|
|||||||
this.CANCEL = t.s('CANCEL');
|
this.CANCEL = t.s('CANCEL');
|
||||||
this.CLOSE = t.s('CLOSE');
|
this.CLOSE = t.s('CLOSE');
|
||||||
this.SAVE = t.s('SAVE');
|
this.SAVE = t.s('SAVE');
|
||||||
|
this.SELECT = t.s('SELECT');
|
||||||
this.OK = t.s('OK');
|
this.OK = t.s('OK');
|
||||||
|
this.RUN = t.s('RUN');
|
||||||
this.NEXT = t.s('NEXT');
|
this.NEXT = t.s('NEXT');
|
||||||
this.SHOW = t.s('SHOW');
|
this.SHOW = t.s('SHOW');
|
||||||
this.HIDE = t.s('HIDE');
|
this.HIDE = t.s('HIDE');
|
||||||
|
|||||||
@@ -102,8 +102,9 @@ function SmartSearchController (
|
|||||||
const rootField = termParts[0].split('.')[0].replace(/^-/, '');
|
const rootField = termParts[0].split('.')[0].replace(/^-/, '');
|
||||||
const listName = $scope.list.name;
|
const listName = $scope.list.name;
|
||||||
const baseRelatedTypePath = `models.${listName}.base.${rootField}.type`;
|
const baseRelatedTypePath = `models.${listName}.base.${rootField}.type`;
|
||||||
|
const relatedTypePath = `models.${listName}.related`;
|
||||||
|
|
||||||
const isRelatedSearchTermField = (_.includes($scope.models[listName].related, rootField));
|
const isRelatedSearchTermField = (_.includes(_.get($scope, relatedTypePath), rootField));
|
||||||
const isBaseModelRelatedSearchTermField = (_.get($scope, baseRelatedTypePath) === 'field');
|
const isBaseModelRelatedSearchTermField = (_.get($scope, baseRelatedTypePath) === 'field');
|
||||||
|
|
||||||
return (isRelatedSearchTermField || isBaseModelRelatedSearchTermField);
|
return (isRelatedSearchTermField || isBaseModelRelatedSearchTermField);
|
||||||
|
|||||||
@@ -44,6 +44,17 @@
|
|||||||
height: 30px;
|
height: 30px;
|
||||||
min-width: 85px;
|
min-width: 85px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Prompt-infoButton{
|
||||||
|
.at-mixin-ButtonColor('at-color-info', 'at-color-default');
|
||||||
|
text-transform: uppercase;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding-left:15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
height: 30px;
|
||||||
|
min-width: 85px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
.Prompt-defaultButton:hover{
|
.Prompt-defaultButton:hover{
|
||||||
background-color: @btn-bg-hov;
|
background-color: @btn-bg-hov;
|
||||||
color: @btn-txt;
|
color: @btn-txt;
|
||||||
|
|||||||
Reference in New Issue
Block a user