mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 01:57:35 -03:30
Fixed bugs from package upgrades. Updated all controllers to pass into form and list generators. Improved accordion styling. Refactored job status page. Tested using minified files and fixed build issues.
This commit is contained in:
parent
2fcb5a1ae4
commit
69b91afaf2
@ -8,7 +8,7 @@ module.exports = function(grunt) {
|
||||
options: {
|
||||
jshintrc: '.jshintrc'
|
||||
},
|
||||
uses_defaults: ['awx/ui/static/js/*','awx/ui/static/lib/ansible/*', '!awx/ui/static/js/awx-min.js']
|
||||
uses_defaults: ['awx/ui/static/js/*','awx/ui/static/lib/ansible/*', '!awx/ui/static/js/awx.min.js']
|
||||
},
|
||||
|
||||
uglify: {
|
||||
@ -18,8 +18,8 @@ module.exports = function(grunt) {
|
||||
},
|
||||
my_target: {
|
||||
files: {
|
||||
'awx/ui/static/js/awx-min.js': ['awx/ui/static/js/**/*.js', 'awx/ui/static/lib/ansible/*.js',
|
||||
'!awx/ui/static/js/awx.min.js']
|
||||
'awx/ui/static/js/awx.min.js': ['awx/ui/static/js/**/*.js', 'awx/ui/static/lib/ansible/*.js',
|
||||
'!awx/ui/static/js/awx.min.js', '!awx/ui/static/js/config.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
60
awx/ui/static/js/awx-min.js
vendored
60
awx/ui/static/js/awx-min.js
vendored
File diff suppressed because one or more lines are too long
@ -213,8 +213,8 @@ function InventoriesList($scope, $rootScope, $location, $log, $routeParams, Rest
|
||||
};
|
||||
}
|
||||
|
||||
InventoriesList.$inject = ['$scope', '$root $scope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'InventoryList', 'GenerateList',
|
||||
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'Clear $scope', 'ProcessErrors',
|
||||
InventoriesList.$inject = ['$scope', '$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'InventoryList', 'GenerateList',
|
||||
'LoadBreadCrumbs', 'Prompt', 'SearchInit', 'PaginateInit', 'ReturnToCaller', 'ClearScope', 'ProcessErrors',
|
||||
'GetBasePath', 'Wait', 'Stream', 'EditInventoryProperties'
|
||||
];
|
||||
|
||||
|
||||
@ -129,7 +129,6 @@ function JobEventsList($filter, $scope, $rootScope, $location, $log, $routeParam
|
||||
for (i = 0; i < set.length; i++) {
|
||||
set[i].event_display = set[i].event_display.replace(/^\u00a0*/g, '');
|
||||
if (set[i].event_level < 3) {
|
||||
set[i].ngclick = "toggleChildren(" + set[i].id + ", \"" + set[i].related.children + "\")";
|
||||
set[i].ngicon = 'fa fa-minus-square-o node-toggle';
|
||||
set[i]['class'] = 'parentNode';
|
||||
} else {
|
||||
@ -216,12 +215,11 @@ function JobEventsList($filter, $scope, $rootScope, $location, $log, $routeParam
|
||||
|
||||
$scope.search(list.iterator, $routeParams.page);
|
||||
|
||||
$scope.toggleChildren = function (id, children) {
|
||||
$scope.toggle = function (id) {
|
||||
ToggleChildren({
|
||||
scope: $scope,
|
||||
list: list,
|
||||
id: id,
|
||||
children: children
|
||||
id: id
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -187,37 +187,40 @@ JobsListCtrl.$inject = ['$scope', '$rootScope', '$location', '$log', '$routePara
|
||||
];
|
||||
|
||||
|
||||
function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobForm, GenerateForm, Rest, Alert, ProcessErrors,
|
||||
LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList, CredentialList,
|
||||
ProjectList, LookUpInit, PromptPasswords, GetBasePath, md5Setup, FormatDate, JobStatusToolTip, Wait) {
|
||||
function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobForm, JobTemplateForm, GenerateForm, Rest,
|
||||
Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList,
|
||||
CredentialList, ProjectList, LookUpInit, PromptPasswords, GetBasePath, md5Setup, FormatDate, JobStatusToolTip, Wait, Empty) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
var defaultUrl = GetBasePath('jobs'),
|
||||
generator = GenerateForm,
|
||||
form = JobForm,
|
||||
master = {},
|
||||
id = $routeParams.id,
|
||||
relatedSets = {},
|
||||
loadingFinishedCount = 0;
|
||||
|
||||
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
|
||||
generator.reset();
|
||||
loadingFinishedCount = 0,
|
||||
templateForm = {};
|
||||
|
||||
generator.inject(JobForm, { mode: 'edit', related: true, scope: $scope });
|
||||
|
||||
$scope.job_id = id;
|
||||
$scope.parseType = 'yaml';
|
||||
$scope.statusSearchSpin = false;
|
||||
|
||||
function getPlaybooks(project) {
|
||||
if (project !== null && project !== '' && project !== undefined) {
|
||||
function getPlaybooks(project, playbook) {
|
||||
if (!Empty(project)) {
|
||||
var url = GetBasePath('projects') + project + '/playbooks/';
|
||||
Rest.setUrl(url);
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var i;
|
||||
$scope.playbook_options = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
for (i = 0; i < data.length; i++) {
|
||||
$scope.playbook_options.push(data[i]);
|
||||
}
|
||||
for (i = 0; i < $scope.playbook_options.length; i++) {
|
||||
if ($scope.playbook_options[i] === playbook) {
|
||||
$scope.playbook = $scope.playbook_options[i];
|
||||
}
|
||||
}
|
||||
$scope.$emit('jobTemplateLoadFinished');
|
||||
})
|
||||
.error(function () {
|
||||
@ -233,22 +236,22 @@ function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, J
|
||||
if ($scope.jobLoadedRemove) {
|
||||
$scope.jobLoadedRemove();
|
||||
}
|
||||
$scope.jobLoadedRemove = $scope.$on('jobLoaded', function (e, related_cloud_credential) {
|
||||
$scope.jobLoadedRemove = $scope.$on('jobLoaded', function (e, related_cloud_credential, project, playbook) {
|
||||
|
||||
getPlaybooks($scope.project);
|
||||
getPlaybooks(project, playbook);
|
||||
|
||||
$scope[form.name + 'ReadOnly'] = ($scope.status === 'new') ? false : true;
|
||||
//$scope[form.name + 'ReadOnly'] = ($scope.status === 'new') ? false : true;
|
||||
|
||||
$('#forks-slider').slider("option", "value", $scope.forks);
|
||||
$('#forks-slider').slider("disable");
|
||||
$('input[type="checkbox"]').attr('disabled', 'disabled');
|
||||
$('input[type="radio"]').attr('disabled', 'disabled');
|
||||
$('#host_config_key-gen-btn').attr('disabled', 'disabled');
|
||||
$('textarea').attr('readonly', 'readonly');
|
||||
//$('#forks-slider').slider("option", "value", $scope.forks);
|
||||
//$('#forks-slider').slider("disable");
|
||||
//$('input[type="checkbox"]').attr('disabled', 'disabled');
|
||||
//$('input[type="radio"]').attr('disabled', 'disabled');
|
||||
//$('#host_config_key-gen-btn').attr('disabled', 'disabled');
|
||||
//$('textarea').attr('readonly', 'readonly');
|
||||
|
||||
// Get job template and display/hide host callback fields
|
||||
Rest.setUrl($scope.template_url);
|
||||
Rest.get()
|
||||
/*Rest.setUrl($scope.template_url);
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var dft = (data.host_config_key) ? 'true' : 'false';
|
||||
$scope.host_config_key = data.host_config_key;
|
||||
@ -265,7 +268,7 @@ function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, J
|
||||
Wait('stop');
|
||||
$scope.callback_url = '<< Job template not found >>';
|
||||
});
|
||||
|
||||
*/
|
||||
if (related_cloud_credential) {
|
||||
//Get the name of the cloud credential
|
||||
Rest.setUrl(related_cloud_credential);
|
||||
@ -281,6 +284,7 @@ function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, J
|
||||
} else {
|
||||
$scope.$emit('jobTemplateLoadFinished');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Turn off 'Wait' after both cloud credential and playbook list come back
|
||||
@ -289,7 +293,7 @@ function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, J
|
||||
}
|
||||
$scope.removeJobTemplateLoadFinished = $scope.$on('jobTemplateLoadFinished', function () {
|
||||
loadingFinishedCount++;
|
||||
if (loadingFinishedCount >= 3) {
|
||||
if (loadingFinishedCount >= 2) {
|
||||
// The initial template load finished. Now load related jobs, which
|
||||
// will turn off the 'working' spinner.
|
||||
Wait('stop');
|
||||
@ -305,13 +309,13 @@ function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, J
|
||||
label: 'Check'
|
||||
}];
|
||||
$scope.verbosity_options = [{
|
||||
value: '0',
|
||||
value: 0,
|
||||
label: 'Default'
|
||||
}, {
|
||||
value: '1',
|
||||
value: 1,
|
||||
label: 'Verbose'
|
||||
}, {
|
||||
value: '3',
|
||||
value: 3,
|
||||
label: 'Debug'
|
||||
}];
|
||||
$scope.playbook_options = null;
|
||||
@ -328,12 +332,34 @@ function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, J
|
||||
Rest.setUrl(defaultUrl + ':id/');
|
||||
Rest.get({ params: { id: id } })
|
||||
.success(function (data) {
|
||||
//LoadBreadCrumbs({ path: '/jobs/' + id, title: data.id + ' - ' + data.summary_fields.job_template.name });
|
||||
var i, cDate, fld, json_obj, related, set;
|
||||
|
||||
var i, fld, json_obj;
|
||||
|
||||
LoadBreadCrumbs();
|
||||
for (fld in form.fields) {
|
||||
|
||||
$scope.status = data.status;
|
||||
$scope.created = FormatDate(data.created);
|
||||
$scope.result_stdout = data.result_stdout;
|
||||
$scope.result_traceback = data.result_traceback;
|
||||
$scope.stdout_rows = calcRows($scope.result_stdout);
|
||||
$scope.traceback_rows = calcRows($scope.result_traceback);
|
||||
|
||||
// Now load the job template form
|
||||
templateForm.addTitle = 'Create Job Templates';
|
||||
templateForm.editTitle = '{{ name }}';
|
||||
templateForm.name = 'job_templates';
|
||||
templateForm.twoColumns = true;
|
||||
templateForm.fields = angular.copy(JobTemplateForm.fields);
|
||||
for (fld in templateForm.fields) {
|
||||
templateForm.fields[fld].readonly = true;
|
||||
}
|
||||
|
||||
$('#ui-accordion-jobs-collapse-0-panel-1').find('div').attr('id','job-template-container');
|
||||
generator.inject(templateForm, { mode: 'edit', id: 'job-template-container', scope: $scope, breadCrumbs: false });
|
||||
|
||||
for (fld in templateForm.fields) {
|
||||
if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) {
|
||||
if (form.fields[fld].type === 'select') {
|
||||
if (JobTemplateForm.fields[fld].type === 'select') {
|
||||
if ($scope[fld + '_options'] && $scope[fld + '_options'].length > 0) {
|
||||
for (i = 0; i < $scope[fld + '_options'].length; i++) {
|
||||
if (data[fld] === $scope[fld + '_options'][i].value) {
|
||||
@ -343,107 +369,36 @@ function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, J
|
||||
} else {
|
||||
$scope[fld] = data[fld];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$scope[fld] = data[fld];
|
||||
}
|
||||
master[fld] = $scope[fld];
|
||||
}
|
||||
|
||||
$scope.id = data.id;
|
||||
$scope.name = (data.summary_fields && data.summary_fields.job_template) ? data.summary_fields.job_template.name : '';
|
||||
|
||||
if (fld === 'variables') {
|
||||
// Parse extra_vars, converting to YAML.
|
||||
if ($.isEmptyObject(data.extra_vars) || data.extra_vars === "{}" || data.extra_vars === "null" ||
|
||||
data.extra_vars === "" || data.extra_vars === null) {
|
||||
$scope.variables = "---";
|
||||
} else {
|
||||
json_obj = JSON.parse(data.extra_vars);
|
||||
$scope.variables = jsyaml.safeDump(json_obj);
|
||||
}
|
||||
master.variables = $scope.variables;
|
||||
}
|
||||
if (form.fields[fld].type === 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
|
||||
$scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||
data.summary_fields[form.fields[fld].sourceModel][form.fields[fld].sourceField];
|
||||
master[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =
|
||||
$scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField];
|
||||
}
|
||||
|
||||
for (fld in form.statusFields) {
|
||||
if (data[fld] !== null && data[fld] !== undefined) {
|
||||
if (fld === 'created') {
|
||||
// Convert created date to local time zone
|
||||
cDate = new Date(data.created);
|
||||
$scope.created = FormatDate(cDate);
|
||||
} else {
|
||||
$scope[fld] = data[fld];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$scope.statusToolTip = JobStatusToolTip(data.status);
|
||||
|
||||
$('form[name="jobs_form"] input[type="text"], form[name="jobs_form"] jobs_form textarea').attr('readonly', 'readonly');
|
||||
$('form[name="jobs_form"] select').prop('disabled', 'disabled');
|
||||
$('form[name="jobs_form"] .lookup-btn').prop('disabled', 'disabled');
|
||||
$('form[name="jobs_form"] .buttons, form[name="jobs_form"] hr').hide();
|
||||
|
||||
$scope.url = data.url;
|
||||
related = data.related;
|
||||
for (set in form.related) {
|
||||
if (related[set]) {
|
||||
relatedSets[set] = {
|
||||
url: related[set],
|
||||
iterator: form.related[set].iterator
|
||||
};
|
||||
if (fld === 'variables') {
|
||||
// Parse extra_vars, converting to YAML.
|
||||
if ($.isEmptyObject(data.extra_vars) || data.extra_vars === "{}" || data.extra_vars === "null" ||
|
||||
data.extra_vars === "" || data.extra_vars === null) {
|
||||
$scope.variables = "---";
|
||||
} else {
|
||||
json_obj = JSON.parse(data.extra_vars);
|
||||
$scope.variables = jsyaml.safeDump(json_obj);
|
||||
}
|
||||
}
|
||||
if (JobTemplateForm.fields[fld].type === 'lookup' && data.summary_fields[JobTemplateForm.fields[fld].sourceModel]) {
|
||||
$scope[JobTemplateForm.fields[fld].sourceModel + '_' + JobTemplateForm.fields[fld].sourceField] =
|
||||
data.summary_fields[JobTemplateForm.fields[fld].sourceModel][JobTemplateForm.fields[fld].sourceField];
|
||||
}
|
||||
}
|
||||
|
||||
$scope.stdout_rows = calcRows($scope.result_stdout);
|
||||
|
||||
$scope.traceback_rows = calcRows($scope.result_traceback);
|
||||
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: data.inventory,
|
||||
list: InventoryList,
|
||||
field: 'inventory'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: data.credential,
|
||||
list: CredentialList,
|
||||
field: 'credential'
|
||||
});
|
||||
|
||||
LookUpInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: data.project,
|
||||
list: ProjectList,
|
||||
field: 'project'
|
||||
});
|
||||
|
||||
// Initialize related search functions. Doing it here to make sure relatedSets object is populated.
|
||||
RelatedSearchInit({
|
||||
scope: $scope,
|
||||
form: form,
|
||||
relatedSets: relatedSets
|
||||
});
|
||||
RelatedPaginateInit({
|
||||
scope: $scope,
|
||||
relatedSets: relatedSets
|
||||
});
|
||||
$scope.template_url = data.related.job_template;
|
||||
$scope.$emit('jobLoaded', data.related.cloud_credential);
|
||||
$scope.id = data.id;
|
||||
$scope.name = (data.summary_fields && data.summary_fields.job_template) ? data.summary_fields.job_template.name : '';
|
||||
$scope.statusToolTip = JobStatusToolTip(data.status);
|
||||
$scope.url = data.url;
|
||||
$scope.project = data.project;
|
||||
|
||||
$scope.$emit('jobLoaded', data.related.cloud_credential, data.project, data.playbook);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
|
||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Failed to retrieve job: ' + $routeParams.id + '. GET status: ' + status });
|
||||
});
|
||||
|
||||
@ -460,11 +415,8 @@ function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, J
|
||||
Wait('stop');
|
||||
})
|
||||
.error(function (data, status) {
|
||||
Wait('stop');
|
||||
ProcessErrors($scope, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Attempt to load job failed. GET returned status: ' + status
|
||||
});
|
||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Attempt to load job failed. GET returned status: ' + status });
|
||||
});
|
||||
};
|
||||
|
||||
@ -477,8 +429,8 @@ function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, J
|
||||
};
|
||||
}
|
||||
|
||||
JobsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobForm',
|
||||
JobsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobForm', 'JobTemplateForm',
|
||||
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit',
|
||||
'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit', 'PromptPasswords',
|
||||
'GetBasePath', 'md5Setup', 'FormatDate', 'JobStatusToolTip', 'Wait'
|
||||
'GetBasePath', 'md5Setup', 'FormatDate', 'JobStatusToolTip', 'Wait', 'Empty'
|
||||
];
|
||||
|
||||
56
awx/ui/static/js/forms/InventoryStatus.js
Normal file
56
awx/ui/static/js/forms/InventoryStatus.js
Normal file
@ -0,0 +1,56 @@
|
||||
/*********************************************
|
||||
* Copyright (c) 2014 AnsibleWorks, Inc.
|
||||
*
|
||||
* InventoryStatus.js
|
||||
*
|
||||
* Use to show inventory sync status
|
||||
*
|
||||
*/
|
||||
angular.module('InventoryStatusDefinition', [])
|
||||
.value('InventoryStatusForm', {
|
||||
|
||||
name: 'inventory_update',
|
||||
editTitle: 'Inventory Status',
|
||||
well: false,
|
||||
'class': 'horizontal-narrow',
|
||||
|
||||
fields: {
|
||||
license_error: {
|
||||
type: 'alertblock',
|
||||
'class': 'alert-info',
|
||||
alertTxt: 'The invenvtory update process exceeded the available number of licensed hosts. ' +
|
||||
'<strong><a ng-click=\"viewLicense()\" href=\"\">View your license</a></strong> ' +
|
||||
'for more information.',
|
||||
ngShow: 'license_error',
|
||||
closeable: true
|
||||
},
|
||||
created: {
|
||||
label: 'Created',
|
||||
type: 'text',
|
||||
readonly: true
|
||||
},
|
||||
status: {
|
||||
label: 'Status',
|
||||
type: 'text',
|
||||
readonly: true,
|
||||
'class': 'nowrap mono-space resizable',
|
||||
rows: '{{ status_rows }}'
|
||||
},
|
||||
result_stdout: {
|
||||
label: 'Std Out',
|
||||
type: 'textarea',
|
||||
ngShow: 'result_stdout',
|
||||
'class': 'nowrap mono-space resizable',
|
||||
readonly: true,
|
||||
rows: '{{ stdout_rows }}'
|
||||
},
|
||||
result_traceback: {
|
||||
label: 'Traceback',
|
||||
type: 'textarea',
|
||||
ngShow: 'result_traceback',
|
||||
'class': 'nowrap mono-space resizable',
|
||||
readonly: true,
|
||||
rows: '{{ traceback_rows }}'
|
||||
}
|
||||
}
|
||||
}); //Form
|
||||
@ -14,6 +14,11 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
name: 'job_templates',
|
||||
twoColumns: true,
|
||||
well: true,
|
||||
base: 'job_templates',
|
||||
collapse: true,
|
||||
collapseTitle: "Properties",
|
||||
collapseMode: 'edit',
|
||||
collapseOpenFirst: true, //Always open first panel
|
||||
|
||||
actions: {
|
||||
stream: {
|
||||
@ -152,7 +157,7 @@ angular.module('JobTemplateFormDefinition', [])
|
||||
column: 1,
|
||||
awPopOver: "<p>Provide a host pattern to further constrain the list of hosts that will be managed or affected by the playbook. " +
|
||||
"Multiple patterns can be separated by ; : or ,</p><p>For more information and examples see " +
|
||||
"<a href=\"http://docs.ansible.com/intro_patterns.html\" target=\"_blank\">the Patters top at docs.ansible.com</a>.</p>",
|
||||
"<a href=\"http://docs.ansible.com/intro_patterns.html\" target=\"_blank\">the Patters topic at docs.ansible.com</a>.</p>",
|
||||
dataTitle: 'Limit',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
|
||||
@ -13,11 +13,12 @@ angular.module('JobFormDefinition', [])
|
||||
editTitle: '{{ id }} - {{ name }}',
|
||||
name: 'jobs',
|
||||
well: true,
|
||||
base: 'jobs',
|
||||
collapse: true,
|
||||
collapseMode: 'edit',
|
||||
collapseTitle: 'Job Template',
|
||||
twoColumns: true,
|
||||
|
||||
collapseTitle: 'Job Status',
|
||||
collapseOpenFirst: true, //Always open first panel
|
||||
|
||||
navigationLinks: {
|
||||
details: {
|
||||
href: "/#/jobs/{{ job_id }}",
|
||||
@ -39,267 +40,7 @@ angular.module('JobFormDefinition', [])
|
||||
},
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
label: 'Job Template',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
readonly: true,
|
||||
column: 1
|
||||
},
|
||||
description: {
|
||||
label: 'Description',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 1
|
||||
},
|
||||
job_type: {
|
||||
label: 'Job Type',
|
||||
type: 'select',
|
||||
ngOptions: 'type.label for type in job_type_options',
|
||||
"default": 'run',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
awPopOver: "<p>When this template is submitted as a job, setting the type to <em>run</em> will execute the playbook, running tasks " +
|
||||
" on the selected hosts.</p> <p>Setting the type to <em>check</em> will not execute the playbook. Instead, ansible will check playbook " +
|
||||
" syntax, test environment setup and report problems.</p>",
|
||||
dataTitle: 'Job Type',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
column: 1
|
||||
},
|
||||
inventory: {
|
||||
label: 'Inventory',
|
||||
type: 'lookup',
|
||||
sourceModel: 'inventory',
|
||||
sourceField: 'name',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
ngClick: 'lookUpInventory()',
|
||||
column: 1,
|
||||
awPopOver: "<p>Select the inventory containing the hosts you want this job to manage.</p>",
|
||||
dataTitle: 'Inventory',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
project: {
|
||||
label: 'Project',
|
||||
type: 'lookup',
|
||||
sourceModel: 'project',
|
||||
sourceField: 'name',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
ngClick: 'lookUpProject()',
|
||||
column: 1,
|
||||
awPopOver: "<p>Select the project containing the playbook you want this job to execute.</p>",
|
||||
dataTitle: 'Project',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
playbook: {
|
||||
label: 'Playbook',
|
||||
type: 'select',
|
||||
ngOptions: 'book for book in playbook_options',
|
||||
id: 'playbook-select',
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
column: 1,
|
||||
awPopOver: "<p>Select the playbook to be executed by this job.</p>",
|
||||
dataTitle: 'Playbook',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
credential: { // FIXME: Lookup only credentials with kind=ssh
|
||||
label: 'Credential',
|
||||
type: 'lookup',
|
||||
sourceModel: 'credential',
|
||||
sourceField: 'name',
|
||||
ngClick: 'lookUpCredential()',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 1,
|
||||
awPopOver: "<p>Select the credential you want the job to use when accessing the remote hosts. Choose the credential containing " +
|
||||
" the username and SSH key or password that Ansbile will need to log into the remote hosts.</p>",
|
||||
dataTitle: 'Credential',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
cloud_credential: { // FIXME: Lookup only credentials with kind=aws/rax
|
||||
label: 'Cloud Credential',
|
||||
type: 'lookup',
|
||||
sourceModel: 'cloud_credential',
|
||||
sourceField: 'name',
|
||||
ngClick: 'lookUpCredential()',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 1,
|
||||
awPopOver: "<p>Selecting an optional cloud credential in the job template will pass along the access credentials to the " +
|
||||
"running playbook, allowing provisioning into the cloud without manually passing parameters to the included modules.</p>",
|
||||
dataTitle: 'Cloud Credential',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
forks: {
|
||||
label: 'Forks',
|
||||
id: 'forks-number',
|
||||
type: 'number',
|
||||
integer: true,
|
||||
min: 0,
|
||||
spinner: true,
|
||||
"class": 'input-small',
|
||||
"default": '0',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 1,
|
||||
disabled: true,
|
||||
awPopOver: "<p>The number of parallel or simultaneous processes to use while executing the playbook.</p>",
|
||||
dataContainer: 'body',
|
||||
dataTitle: 'Forks',
|
||||
dataPlacement: 'right'
|
||||
},
|
||||
limit: {
|
||||
label: 'Limit',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 1,
|
||||
awPopOver: "<p>Provide a host pattern to further constrain the list of hosts that will be managed or affected by the playbook. " +
|
||||
"Multiple patterns can be separated by ; : or ,</p><p>For more information and examples see the " +
|
||||
"<a href=\"http://ansible.cc/docs/patterns.html#selecting-targets\" target=\"_blank\">Selecting Targets section</a> under Inventory and Patterns " +
|
||||
" in the Ansible documentation.</p>",
|
||||
dataContainer: 'body',
|
||||
dataTitle: 'Limit',
|
||||
dataPlacement: 'right'
|
||||
},
|
||||
verbosity: {
|
||||
label: 'Verbosity',
|
||||
type: 'select',
|
||||
ngOptions: 'v.label for v in verbosity_options',
|
||||
"default": 0,
|
||||
addRequired: true,
|
||||
editRequired: true,
|
||||
column: 1,
|
||||
awPopOver: "<p>Control the level of output ansible will produce as the playbook executes.</p>",
|
||||
dataTitle: 'Verbosity',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body'
|
||||
},
|
||||
variables: {
|
||||
label: 'Extra Variables',
|
||||
type: 'textarea',
|
||||
rows: 6,
|
||||
"class": 'span12',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 2,
|
||||
awPopOver: "<p>Pass extra command line variables to the playbook. This is the -e or --extra-vars command line parameter " +
|
||||
"for ansible-playbook. Provide key/value pairs using either YAML or JSON.</p>" +
|
||||
"JSON:<br />\n" +
|
||||
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
|
||||
"YAML:<br />\n" +
|
||||
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n",
|
||||
dataTitle: 'Extra Variables',
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right'
|
||||
},
|
||||
job_tags: {
|
||||
label: 'Job Tags',
|
||||
type: 'textarea',
|
||||
rows: 1,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
'class': 'span12',
|
||||
column: 2,
|
||||
awPopOver: "<p>Provide a comma separated list of tags.</p>\n" +
|
||||
"<p>Tags are useful when you have a large playbook, and you want to run a specific part of a play or task.</p>" +
|
||||
"<p>For example, you might have a task consisiting of a long list of actions. Tag values can be assigned to each action. " +
|
||||
"Suppose the actions have been assigned tag values of "configuration", "packages" and "install".</p>" +
|
||||
"<p>If you just want to run the "configuration" and "packages" actions, you would enter the following here " +
|
||||
"in the Job Tags field:</p>\n" +
|
||||
"<blockquote>configuration,packages</blockquote>\n",
|
||||
dataTitle: "Job Tags",
|
||||
dataContainer: 'body',
|
||||
dataPlacement: "right"
|
||||
},
|
||||
allow_callbacks: {
|
||||
label: 'Allow Callbacks',
|
||||
type: 'checkbox',
|
||||
addRequired: false,
|
||||
editRequird: false,
|
||||
trueValue: 'true',
|
||||
falseValue: 'false',
|
||||
ngChange: "toggleCallback('host_config_key')",
|
||||
"class": "span12",
|
||||
column: 2,
|
||||
awPopOver: "<p>Create a callback URL a host can use to contact Tower and request a configuration update " +
|
||||
"using the job template. The URL will look like the following:</p>\n" +
|
||||
"<p class=\"code-breakable\">http://your.server.com:999/api/v1/job_templates/1/callback/</p>" +
|
||||
"<p>The request from the host must be a POST. Here is an example using curl:</p>\n" +
|
||||
"<p class=\"code-breakable\">curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
|
||||
"http://your.server.com:999/api/v1/job_templates/1/callback/</p>\n" +
|
||||
"<p>Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address " +
|
||||
"in one of your defined inventories, the request will be denied.</p>" +
|
||||
"<p>Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.</p>",
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
dataTitle: 'Callback URL'
|
||||
},
|
||||
callback_url: {
|
||||
label: 'Callback URL',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
readonly: true,
|
||||
column: 2,
|
||||
required: false,
|
||||
'class': 'span12',
|
||||
awPopOver: "<p>Using this URL a host can contact Tower and request a configuration update using the job " +
|
||||
"template. The request from the host must be a POST. Here is an example using curl:</p>\n" +
|
||||
"<p class=\"code-breakable\">curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
|
||||
"http://your.server.com:999/api/v1/job_templates/1/callback/</p>\n" +
|
||||
"<p>Note the requesting host must be defined in your inventory. If ansible fails to locate the host either by name or IP address " +
|
||||
"in one of your defined inventories, the request will be denied.</p>" +
|
||||
"<p>Successful requests will result in an entry on the Jobs tab, where the results and history can be viewed.</p>",
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
dataTitle: 'Callback URL'
|
||||
},
|
||||
host_config_key: {
|
||||
label: 'Host Config Key',
|
||||
type: 'text',
|
||||
ngShow: "allow_callbacks",
|
||||
genMD5: true,
|
||||
column: 2,
|
||||
awPopOver: "<p>When contacting Tower using the callback URL, the calling host must authenticate by including " +
|
||||
"this key in the POST data of the request. Here's an example using curl:</p>\n" +
|
||||
"<p class=\"code-breakable\">curl --data \"host_config_key=5a8ec154832b780b9bdef1061764ae5a\" " +
|
||||
"http://your.server.com:999/api/v1/job_templates/1/callback/</p>\n",
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body'
|
||||
}
|
||||
},
|
||||
|
||||
buttons: {
|
||||
save: {
|
||||
label: 'Save',
|
||||
icon: 'icon-ok',
|
||||
"class": 'btn-success',
|
||||
ngClick: 'formSave()',
|
||||
ngDisabled: true
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
label: 'Reset',
|
||||
icon: 'icon-undo',
|
||||
'class': 'btn btn-default',
|
||||
ngDisabled: true
|
||||
}
|
||||
},
|
||||
|
||||
statusFields: {
|
||||
status: {
|
||||
//label: 'Job Status',
|
||||
type: 'custom',
|
||||
control: "<div class=\"job-detail-status\"><span style=\"padding-right: 15px; font-weight: bold;\">Status</span> " +
|
||||
"<i class=\"fa icon-job-{{ status }}\"></i> {{ status }}</div>",
|
||||
@ -330,7 +71,7 @@ angular.module('JobFormDefinition', [])
|
||||
}
|
||||
},
|
||||
|
||||
statusActions: {
|
||||
actions: {
|
||||
refresh: {
|
||||
dataPlacement: 'top',
|
||||
icon: "icon-refresh",
|
||||
@ -341,6 +82,17 @@ angular.module('JobFormDefinition', [])
|
||||
awToolTip: "Refresh the page",
|
||||
ngClick: "refresh()"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
related: {
|
||||
job_template: {
|
||||
type: 'collection',
|
||||
title: 'Job Tempate',
|
||||
iterator: 'job',
|
||||
index: false,
|
||||
open: false,
|
||||
|
||||
fields: { }
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -11,7 +11,8 @@
|
||||
|
||||
angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'GroupListDefinition', 'SearchHelper',
|
||||
'PaginationHelpers', 'ListGenerator', 'AuthService', 'GroupsHelper', 'InventoryHelper', 'SelectionHelper',
|
||||
'JobSubmissionHelper', 'RefreshHelper', 'PromptDialog', 'CredentialsListDefinition', 'InventoryTree'
|
||||
'JobSubmissionHelper', 'RefreshHelper', 'PromptDialog', 'CredentialsListDefinition', 'InventoryTree',
|
||||
'InventoryStatusDefinition'
|
||||
])
|
||||
|
||||
.factory('GetSourceTypeOptions', ['Rest', 'ProcessErrors', 'GetBasePath',
|
||||
|
||||
@ -92,7 +92,7 @@ angular.module('InventoriesListDefinition', [])
|
||||
},
|
||||
"delete": {
|
||||
label: 'Delete',
|
||||
ngClick: "deleteInventory(inventory.id, inventory.names')",
|
||||
ngClick: "deleteInventory(inventory.id, inventory.names)",
|
||||
awToolTip: 'Delete inventory',
|
||||
dataPlacement: 'top'
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ angular.module('InventoryGroupsDefinition', [])
|
||||
cancel: {
|
||||
//label: 'Cancel',
|
||||
mode: 'all',
|
||||
ngClick: "cancelUpdate({{ group.id }})",
|
||||
ngClick: "cancelUpdate(group.id)",
|
||||
awToolTip: "Cancel sync process",
|
||||
'class': 'red-txt',
|
||||
ngShow: "group.id > 1 && (group.status == 'running' || group.status == 'pending' || group.status == 'updating')",
|
||||
@ -108,7 +108,7 @@ angular.module('InventoryGroupsDefinition', [])
|
||||
edit: {
|
||||
//label: 'Edit',
|
||||
mode: 'all',
|
||||
ngClick: "editGroup({{ group.group_id + ',' + group.id }})",
|
||||
ngClick: "editGroup(group.group_id, group.id)",
|
||||
awToolTip: 'Edit group',
|
||||
ngShow: "group.id > 1", // hide for all hosts
|
||||
dataPlacement: "top"
|
||||
@ -116,7 +116,7 @@ angular.module('InventoryGroupsDefinition', [])
|
||||
"delete": {
|
||||
//label: 'Delete',
|
||||
mode: 'all',
|
||||
ngClick: "deleteGroup({{ group.id + ',' + group.group_id }})",
|
||||
ngClick: "deleteGroup(group.id, group.group_id)",
|
||||
awToolTip: 'Delete group',
|
||||
ngShow: "group.id != 1", // hide for all hosts
|
||||
dataPlacement: "top"
|
||||
|
||||
@ -64,14 +64,14 @@ angular.module('JobEventsListDefinition', [])
|
||||
}],
|
||||
nosort: true,
|
||||
searchable: false,
|
||||
ngClick: 'viewJobEvent({{ jobevent.id }})',
|
||||
ngClick: 'viewJobEvent(jobevent.id)',
|
||||
awToolTip: '{{ jobevent.statusBadgeToolTip }}',
|
||||
dataPlacement: 'top',
|
||||
badgeIcon: 'fa icon-job-{{ jobevent.status }}',
|
||||
badgePlacement: 'left',
|
||||
badgeToolTip: '{{ jobevent.statusBadgeToolTip }}',
|
||||
badgeTipPlacement: 'top',
|
||||
badgeNgClick: 'viewJobEvent({{ jobevent.id }})'
|
||||
badgeNgClick: 'viewJobEvent(jobevent.id)'
|
||||
},
|
||||
event_display: {
|
||||
label: 'Event',
|
||||
|
||||
@ -407,12 +407,16 @@ dd {
|
||||
|
||||
.help-link,
|
||||
.help-link:active,
|
||||
.help-link:visited {
|
||||
.help-link:visited,
|
||||
.ui-widget-content a.help-link,
|
||||
.ui-widget-content a.help-link:active,
|
||||
.ui-widget-content a.help-link:visited {
|
||||
color: @grey;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.help-link:hover {
|
||||
.help-link:hover,
|
||||
.ui-widget-content a.help-link:hover {
|
||||
color: @black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@ -59,11 +59,11 @@ angular.module('AuthService', ['ngCookies', 'Utilities'])
|
||||
var scope = angular.element(document.getElementById('main-view')).scope();
|
||||
scope.$destroy();
|
||||
$rootScope.$destroy();
|
||||
$cookieStore.remove('accordions');
|
||||
$cookieStore.remove('token');
|
||||
$cookieStore.remove('token_expires');
|
||||
$cookieStore.remove('current_user');
|
||||
$cookieStore.remove('lastPath');
|
||||
$cookieStore.remove('license');
|
||||
$cookieStore.put('userLoggedIn', false);
|
||||
$cookieStore.put('sessionExpired', false);
|
||||
$cookieStore.remove('lastPath', '/home');
|
||||
|
||||
@ -113,7 +113,6 @@ angular.module('InventoryTree', ['Utilities', 'RestServices', 'GroupsHelper', 'P
|
||||
event_level: level,
|
||||
children: children,
|
||||
ngicon: (sorted[i].children.length > 0) ? 'fa fa-minus-square-o node-toggle' : 'fa fa-square-o node-no-toggle',
|
||||
ngclick: 'toggle(' + id + ')',
|
||||
related: {
|
||||
children: (sorted[i].children.length > 0) ? sorted[i].related.children : '',
|
||||
inventory_source: sorted[i].related.inventory_source
|
||||
|
||||
@ -262,12 +262,12 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (/_/.test(paths[i])) {
|
||||
//if (/_/.test(paths[i])) {
|
||||
// replace '_' with space and uppercase each word
|
||||
paths[i] = paths[i].replace(/(?:^|_)\S/g, toUppercase)
|
||||
.replace(/_/g, ' ');
|
||||
}
|
||||
title = paths[i].charAt(0).toUpperCase() + paths[i].slice(1);
|
||||
|
||||
//}
|
||||
//title = paths[i].charAt(0).toUpperCase() + paths[i].slice(1);
|
||||
title = paths[i].replace(/(?:^|_)\S/g, toUppercase).replace(/_/g, ' ');
|
||||
$rootScope.breadcrumbs.push({
|
||||
title: title,
|
||||
path: ppath + '/' + paths[i]
|
||||
@ -456,7 +456,7 @@ angular.module('Utilities', ['RestServices', 'Utilities'])
|
||||
|
||||
/*
|
||||
* Wrapper for data filter- an attempt to insure all dates display in
|
||||
* the same format. Pass in date object.
|
||||
* the same format. Pass in date object or string. See: http://docs.angularjs.org/api/ng.filter:date
|
||||
*/
|
||||
.factory('FormatDate', ['$filter',
|
||||
function ($filter) {
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
* to access the primary model objects.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('ApiLoader', ['Utilities'])
|
||||
|
||||
@ -321,9 +321,9 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Job
|
||||
//
|
||||
// Enable jqueryui slider widget on a numeric input field
|
||||
//
|
||||
// <input type="number" ng-slider name="myfield" min="0" max="100" />
|
||||
// <input type="number" aw-slider name="myfield" min="0" max="100" />
|
||||
//
|
||||
.directive('ngSlider', [ function() {
|
||||
.directive('awSlider', [ function() {
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link: function(scope, elm, attrs, ctrl) {
|
||||
@ -333,6 +333,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Job
|
||||
step: 1,
|
||||
min: elm.attr('min'),
|
||||
max: elm.attr('max'),
|
||||
disabled: (elm.attr('readonly')) ? true : false,
|
||||
slide: function(e,u) {
|
||||
ctrl.$setViewValue(u.value);
|
||||
ctrl.$setValidity('required',true);
|
||||
@ -384,9 +385,9 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Job
|
||||
//
|
||||
// Enable jqueryui spinner widget on a numeric input field
|
||||
//
|
||||
// <input type="number" ng-spinner name="myfield" min="0" max="100" />
|
||||
// <input type="number" aw-spinner name="myfield" min="0" max="100" />
|
||||
//
|
||||
.directive('ngSpinner', [ function() {
|
||||
.directive('awSpinner', [ function() {
|
||||
return {
|
||||
require: 'ngModel',
|
||||
link: function(scope, elm, attrs, ctrl) {
|
||||
@ -398,6 +399,7 @@ angular.module('AWDirectives', ['RestServices', 'Utilities', 'AuthService', 'Job
|
||||
min: elm.attr('min'),
|
||||
max: elm.attr('max'),
|
||||
numberFormat: "d",
|
||||
disabled: (elm.attr('readonly')) ? true : false,
|
||||
spin: function(e, u) {
|
||||
ctrl.$setViewValue(u.value);
|
||||
ctrl.$setValidity('required',true);
|
||||
|
||||
@ -13,9 +13,9 @@
|
||||
angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
|
||||
|
||||
.factory('GenerateForm', ['$rootScope', '$location', '$cookieStore', '$compile', 'SearchWidget', 'PaginateWidget', 'Attr',
|
||||
'Icon', 'Column', 'NavigationLink', 'HelpCollapse', 'Button', 'DropDown', 'Empty', 'SelectIcon',
|
||||
'Icon', 'Column', 'NavigationLink', 'HelpCollapse', 'Button', 'DropDown', 'Empty', 'SelectIcon', 'Store',
|
||||
function ($rootScope, $location, $cookieStore, $compile, SearchWidget, PaginateWidget, Attr, Icon, Column, NavigationLink,
|
||||
HelpCollapse, Button, DropDown, Empty, SelectIcon) {
|
||||
HelpCollapse, Button, DropDown, Empty, SelectIcon, Store) {
|
||||
return {
|
||||
|
||||
setForm: function (form) { this.form = form; },
|
||||
@ -283,6 +283,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
|
||||
active: 0
|
||||
});
|
||||
} else {
|
||||
// For help collapse, toggle the plus/minus icon
|
||||
this.scope.accordionToggle = function (selector) {
|
||||
$(selector).collapse('toggle');
|
||||
if ($(selector + '-icon').hasClass('fa-minus')) {
|
||||
@ -293,25 +294,28 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
|
||||
};
|
||||
|
||||
$('.jqui-accordion').each(function () {
|
||||
|
||||
var active = false,
|
||||
list = $cookieStore.get('accordions'),
|
||||
list = Store('accordions'),
|
||||
found = false,
|
||||
id, base, i;
|
||||
|
||||
if (list) {
|
||||
id = $(this).attr('id');
|
||||
base = ($location.path().replace(/^\//, '').split('/')[0]);
|
||||
for (i = 0; i < list.length && found === false; i++) {
|
||||
if (list[i].base === base && list[i].id === id) {
|
||||
found = true;
|
||||
active = list[i].active;
|
||||
if ($(this).attr('data-open-first')) {
|
||||
active = 0;
|
||||
}
|
||||
else {
|
||||
if (list) {
|
||||
id = $(this).attr('id');
|
||||
base = ($location.path().replace(/^\//, '').split('/')[0]);
|
||||
for (i = 0; i < list.length && found === false; i++) {
|
||||
if (list[i].base === base && list[i].id === id) {
|
||||
found = true;
|
||||
active = list[i].active;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found === false && $(this).attr('data-open') === 'true') {
|
||||
active = 0;
|
||||
if (found === false && $(this).attr('data-open') === 'true') {
|
||||
active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$(this).accordion({
|
||||
@ -319,16 +323,19 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
|
||||
heightStyle: 'content',
|
||||
active: active,
|
||||
activate: function () {
|
||||
// Maintain in local storage of list of all accordions by page, recording
|
||||
// the active panel for each. If user navigates away and comes back,
|
||||
// we can activate the last panely viewed.
|
||||
$('.jqui-accordion').each(function () {
|
||||
var active = $(this).accordion('option', 'active'),
|
||||
id = $(this).attr('id'),
|
||||
base = ($location.path().replace(/^\//, '').split('/')[0]),
|
||||
list = $cookieStore.get('accordions'),
|
||||
i, found;
|
||||
if (list === null || list === undefined) {
|
||||
list = Store('accordions'),
|
||||
found = false,
|
||||
i;
|
||||
if (!list) {
|
||||
list = [];
|
||||
}
|
||||
found = false;
|
||||
for (i = 0; i < list.length && found === false; i++) {
|
||||
if (list[i].base === base && list[i].id === id) {
|
||||
found = true;
|
||||
@ -342,7 +349,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
|
||||
active: active
|
||||
});
|
||||
}
|
||||
$cookieStore.put('accordions', list);
|
||||
Store('accordions', list);
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -728,7 +735,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
|
||||
html += (options.mode === 'edit' && field.editRequired) ? "required " : "";
|
||||
html += (options.mode === 'add' && field.addRequired) ? "required " : "";
|
||||
html += (field.multiSelect) ? "multiple " : "";
|
||||
html += (field.readonly) ? "readonly " : "";
|
||||
html += (field.readonly) ? "disabled " : "";
|
||||
html += (field.awRequiredWhen) ? "data-awrequired-init=\"" + field.awRequiredWhen.init + "\" aw-required-when=\"" +
|
||||
field.awRequiredWhen.variable + "\" " : "";
|
||||
html += ">\n";
|
||||
@ -762,11 +769,14 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
|
||||
html += "<input ";
|
||||
html += (field.spinner) ? "" : "type=\"text\" ";
|
||||
html += "\" value=\"" + field['default'] + "\" ";
|
||||
html += "class=\"form-control";
|
||||
html += "class=\"";
|
||||
if (!field.slider && !field.spinner) {
|
||||
html += "form-control";
|
||||
}
|
||||
html += (field['class']) ? " " + field['class'] : "";
|
||||
html += "\" ";
|
||||
html += (field.slider) ? "ng-slider=\"" + fld + "\" " : "";
|
||||
html += (field.spinner) ? "ng-spinner=\"" + fld + "\" " : "";
|
||||
html += (field.slider) ? "aw-slider=\"" + fld + "\" " : "";
|
||||
html += (field.spinner) ? "aw-spinner=\"" + fld + "\" " : "";
|
||||
html += "ng-model=\"" + fld + '" ';
|
||||
html += 'name="' + fld + '" ';
|
||||
html += buildId(field, fld, this.form);
|
||||
@ -937,7 +947,9 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
|
||||
|
||||
html += "<div class=\"input-group\">\n";
|
||||
html += "<span class=\"input-group-btn\">\n";
|
||||
html += "<button type=\"button\" class=\"lookup-btn btn btn-default\" " + this.attr(field, 'ngClick') + "><i class=\"fa fa-search\"></i></button>\n";
|
||||
html += "<button type=\"button\" class=\"lookup-btn btn btn-default\" " + this.attr(field, 'ngClick');
|
||||
html += (field.readonly || field.showonly) ? " disabled " : "";
|
||||
html += "><i class=\"fa fa-search\"></i></button>\n";
|
||||
html += "</span>\n";
|
||||
html += "<input type=\"text\" class=\"form-control input-medium lookup\" ";
|
||||
html += "ng-model=\"" + field.sourceModel + '_' + field.sourceField + "\" ";
|
||||
@ -947,6 +959,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
|
||||
html += (field.id) ? this.attr(field, 'id') : "";
|
||||
html += (field.placeholder) ? this.attr(field, 'placeholder') : "";
|
||||
html += (options.mode === 'edit' && field.editRequired) ? "required " : "";
|
||||
html += (field.readonly || field.showonly) ? "readonly " : "";
|
||||
html += (field.awRequiredWhen) ? "data-awrequired-init=\"" + field.awRequiredWhen.init + "\" aw-required-when=\"" +
|
||||
field.awRequiredWhen.variable + "\" " : "";
|
||||
html += " awlookup >\n";
|
||||
@ -1063,7 +1076,7 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
|
||||
// Generate HTML. Do NOT call this function directly. Called by inject(). Returns an HTML
|
||||
// string to be injected into the current view.
|
||||
//
|
||||
var act, action, btn, button, fld, field, html = '', i, section, group,
|
||||
var btn, button, fld, field, html = '', i, section, group,
|
||||
tab, sectionShow, offset, width;
|
||||
|
||||
if (!this.modal && (options.breadCrumbs === undefined || options.breadCrumbs === true)) {
|
||||
@ -1073,263 +1086,229 @@ angular.module('FormGenerator', ['GeneratorHelpers', 'ngCookies', 'Utilities'])
|
||||
html += this.breadCrumbs(options);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.form.collapse && this.form.collapseMode === options.mode) {
|
||||
html += "<div id=\"" + this.form.name + "-collapse-0\" ";
|
||||
html += (this.form.collapseOpen) ? "data-open=\"true\" " : "";
|
||||
html += (this.form.collapseOpenFirst) ? "data-open-first=\"true\" " : "";
|
||||
html += "class=\"jqui-accordion\">\n";
|
||||
html += "<h3>" + this.form.collapseTitle + "</h3>\n";
|
||||
html += "<div>\n";
|
||||
options.collapseAlreadyStarted = true;
|
||||
}
|
||||
|
||||
if ((!this.modal && this.form.statusFields)) {
|
||||
// Add status fields section (used in Jobs form)
|
||||
html += "<div class=\"well\">\n";
|
||||
if (this.form.statusActions) {
|
||||
html += "<div class=\"list-actions\">\n";
|
||||
for (action in this.form.statusActions) {
|
||||
act = this.form.statusActions[action];
|
||||
// Start the well
|
||||
if (!this.modal && this.has('well')) {
|
||||
if ( !(this.form.collapse && this.form.collapseMode === options.mode)) {
|
||||
html += "<div class=\"well\">\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.modal && this.form.actions) {
|
||||
html += this.getActions(options);
|
||||
}
|
||||
|
||||
// Add a title and optionally a close button (used on Inventory->Groups)
|
||||
/*if ((!options.modal) && this.form.showTitle) {
|
||||
html += "<div class=\"form-title\">";
|
||||
html += (options.mode === 'edit') ? this.form.editTitle : this.form.addTitle;
|
||||
if (this.has('titleActions')) {
|
||||
html += "<div class=\"title-actions pull-right\">\n";
|
||||
for (btn in this.form.titleActions) {
|
||||
html += this.button({
|
||||
btn: act,
|
||||
action: action,
|
||||
btn: this.form.titleActions[btn],
|
||||
action: btn,
|
||||
toolbar: true
|
||||
});
|
||||
}
|
||||
html += "</div>\n";
|
||||
}
|
||||
html += "<div class=\"form status-fields\">\n";
|
||||
for (fld in this.form.statusFields) {
|
||||
field = this.form.statusFields[fld];
|
||||
html += this.buildField(fld, field, options, this.form);
|
||||
}
|
||||
html += "</div><!-- status fields -->\n";
|
||||
html += "</div><!-- well -->\n";
|
||||
}
|
||||
html += "</div>\n";
|
||||
html += "<hr class=\"form-title-hr\">\n";
|
||||
}*/
|
||||
|
||||
if (this.form.fieldsAsHeader) {
|
||||
html += "<div class=\"well\">\n";
|
||||
html += "<form class=\"form-inline\" name=\"" + this.form.name + "_form\" id=\"" + this.form.name + "_form\" novalidate >\n";
|
||||
html += "<form class=\"";
|
||||
html += (this.form.horizontal) ? "form-horizontal" : "";
|
||||
html += (this.form['class']) ? ' ' + this.form['class'] : '';
|
||||
html += "\" name=\"" + this.form.name + "_form\" id=\"" + this.form.name + "_form\" autocomplete=\"off\" novalidate>\n";
|
||||
html += "<div ng-show=\"flashMessage != null && flashMessage != undefined\" class=\"alert alert-info\">{{ flashMessage }}</div>\n";
|
||||
|
||||
if (this.form.twoColumns) {
|
||||
html += "<div class=\"row\">\n";
|
||||
html += "<div class=\"col-lg-6\">\n";
|
||||
for (fld in this.form.fields) {
|
||||
field = this.form.fields[fld];
|
||||
html += this.headerField(fld, field, options);
|
||||
if (field.column === 1) {
|
||||
html += this.buildField(fld, field, options, this.form);
|
||||
}
|
||||
}
|
||||
html += "</div><!-- column 1 -->\n";
|
||||
html += "<div class=\"col-lg-6\">\n";
|
||||
for (fld in this.form.fields) {
|
||||
field = this.form.fields[fld];
|
||||
if (field.column === 2) {
|
||||
html += this.buildField(fld, field, options, this.form);
|
||||
}
|
||||
}
|
||||
html += "</div><!-- column 2 -->\n";
|
||||
html += "</div>\n";
|
||||
} else if (this.form.tabs) {
|
||||
html += "<ul id=\"" + this.form.name + "_tabs\" class=\"nav nav-tabs\">\n";
|
||||
for (i = 0; i < this.form.tabs.length; i++) {
|
||||
tab = this.form.tabs[i];
|
||||
html += "<li";
|
||||
if (i === 0) {
|
||||
html += " class=\"active\"";
|
||||
}
|
||||
html += "><a href=\"#" + tab.name + "\" data-toggle=\"tab\">" + tab.label + "</a></li>\n";
|
||||
}
|
||||
html += "</ul>\n";
|
||||
html += "<div class=\"tab-content\">\n";
|
||||
for (i = 0; i < this.form.tabs.length; i++) {
|
||||
tab = this.form.tabs[i];
|
||||
html += "<div class=\"tab-pane";
|
||||
if (i === 0) {
|
||||
html += " active";
|
||||
}
|
||||
html += "\" id=\"" + tab.name + "\">\n";
|
||||
for (fld in this.form.fields) {
|
||||
if (this.form.fields[fld].tab === tab.name) {
|
||||
html += this.buildField(fld, this.form.fields[fld], options, this.form);
|
||||
}
|
||||
}
|
||||
html += "</div>\n";
|
||||
}
|
||||
html += "</form>\n";
|
||||
html += "</div>\n";
|
||||
} else {
|
||||
|
||||
if (this.form.collapse && this.form.collapseMode === options.mode) {
|
||||
html += "<div id=\"" + this.form.name + "-collapse-0\" ";
|
||||
html += (this.form.collapseOpen) ? "data-open=\"true\" " : "";
|
||||
html += "class=\"jqui-accordion\">\n";
|
||||
html += "<h3>" + this.form.collapseTitle + "</h3>\n";
|
||||
html += "<div>\n";
|
||||
options.collapseAlreadyStarted = true;
|
||||
}
|
||||
|
||||
// Start the well
|
||||
if (!this.modal && this.has('well')) {
|
||||
if ( !(this.form.collapse && this.form.collapseMode === options.mode)) {
|
||||
html += "<div class=\"well\">\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.modal && this.form.actions) {
|
||||
html += this.getActions(options);
|
||||
}
|
||||
|
||||
// Add a title and optionally a close button (used on Inventory->Groups)
|
||||
if ((!options.modal) && this.form.showTitle) {
|
||||
html += "<div class=\"form-title\">";
|
||||
html += (options.mode === 'edit') ? this.form.editTitle : this.form.addTitle;
|
||||
if (this.has('titleActions')) {
|
||||
html += "<div class=\"title-actions pull-right\">\n";
|
||||
for (btn in this.form.titleActions) {
|
||||
html += this.button({
|
||||
btn: this.form.titleActions[btn],
|
||||
action: btn,
|
||||
toolbar: true
|
||||
});
|
||||
// original, single-column form
|
||||
section = '';
|
||||
group = '';
|
||||
for (fld in this.form.fields) {
|
||||
field = this.form.fields[fld];
|
||||
if (!(options.modal && field.excludeModal)) {
|
||||
if (field.group && field.group !== group) {
|
||||
if (group !== '') {
|
||||
html += "</div>\n";
|
||||
}
|
||||
html += "<div class=\"well\">\n";
|
||||
html += "<h5>" + field.group + "</h5>\n";
|
||||
group = field.group;
|
||||
}
|
||||
html += "</div>\n";
|
||||
if (field.section && field.section !== section) {
|
||||
if (section !== '') {
|
||||
html += "</div>\n";
|
||||
} else {
|
||||
html += "</div>\n";
|
||||
html += "<div id=\"" + this.form.name + "-collapse\" class=\"jqui-accordion-modal\">\n";
|
||||
}
|
||||
sectionShow = (this.form[field.section + 'Show']) ? " ng-show=\"" + this.form[field.section + 'Show'] + "\"" : "";
|
||||
html += "<h3" + sectionShow + ">" + field.section + "</h3>\n";
|
||||
html += "<div" + sectionShow + ">\n";
|
||||
section = field.section;
|
||||
}
|
||||
html += this.buildField(fld, field, options, this.form);
|
||||
}
|
||||
}
|
||||
if (section !== '') {
|
||||
html += "</div>\n</div>\n";
|
||||
}
|
||||
if (group !== '') {
|
||||
html += "</div>\n";
|
||||
html += "<hr class=\"form-title-hr\">\n";
|
||||
}
|
||||
|
||||
html += "<form class=\"";
|
||||
html += (this.form.horizontal) ? "form-horizontal" : "";
|
||||
html += (this.form['class']) ? ' ' + this.form['class'] : '';
|
||||
html += "\" name=\"" + this.form.name + "_form\" id=\"" + this.form.name + "_form\" autocomplete=\"off\" novalidate>\n";
|
||||
html += "<div ng-show=\"flashMessage != null && flashMessage != undefined\" class=\"alert alert-info\">{{ flashMessage }}</div>\n";
|
||||
|
||||
if (this.form.twoColumns) {
|
||||
html += "<div class=\"row\">\n";
|
||||
html += "<div class=\"col-lg-6\">\n";
|
||||
for (fld in this.form.fields) {
|
||||
field = this.form.fields[fld];
|
||||
if (field.column === 1) {
|
||||
html += this.buildField(fld, field, options, this.form);
|
||||
}
|
||||
}
|
||||
html += "</div><!-- column 1 -->\n";
|
||||
html += "<div class=\"col-lg-6\">\n";
|
||||
for (fld in this.form.fields) {
|
||||
field = this.form.fields[fld];
|
||||
if (field.column === 2) {
|
||||
html += this.buildField(fld, field, options, this.form);
|
||||
}
|
||||
}
|
||||
html += "</div><!-- column 2 -->\n";
|
||||
html += "</div>\n";
|
||||
} else if (this.form.tabs) {
|
||||
html += "<ul id=\"" + this.form.name + "_tabs\" class=\"nav nav-tabs\">\n";
|
||||
for (i = 0; i < this.form.tabs.length; i++) {
|
||||
tab = this.form.tabs[i];
|
||||
html += "<li";
|
||||
if (i === 0) {
|
||||
html += " class=\"active\"";
|
||||
}
|
||||
html += "><a href=\"#" + tab.name + "\" data-toggle=\"tab\">" + tab.label + "</a></li>\n";
|
||||
}
|
||||
html += "</ul>\n";
|
||||
html += "<div class=\"tab-content\">\n";
|
||||
for (i = 0; i < this.form.tabs.length; i++) {
|
||||
tab = this.form.tabs[i];
|
||||
html += "<div class=\"tab-pane";
|
||||
if (i === 0) {
|
||||
html += " active";
|
||||
}
|
||||
html += "\" id=\"" + tab.name + "\">\n";
|
||||
for (fld in this.form.fields) {
|
||||
if (this.form.fields[fld].tab === tab.name) {
|
||||
html += this.buildField(fld, this.form.fields[fld], options, this.form);
|
||||
}
|
||||
}
|
||||
html += "</div>\n";
|
||||
}
|
||||
html += "</div>\n";
|
||||
} else {
|
||||
// original, single-column form
|
||||
section = '';
|
||||
group = '';
|
||||
for (fld in this.form.fields) {
|
||||
field = this.form.fields[fld];
|
||||
if (!(options.modal && field.excludeModal)) {
|
||||
if (field.group && field.group !== group) {
|
||||
if (group !== '') {
|
||||
html += "</div>\n";
|
||||
}
|
||||
html += "<div class=\"well\">\n";
|
||||
html += "<h5>" + field.group + "</h5>\n";
|
||||
group = field.group;
|
||||
}
|
||||
if (field.section && field.section !== section) {
|
||||
if (section !== '') {
|
||||
html += "</div>\n";
|
||||
} else {
|
||||
html += "</div>\n";
|
||||
html += "<div id=\"" + this.form.name + "-collapse\" class=\"jqui-accordion-modal\">\n";
|
||||
}
|
||||
sectionShow = (this.form[field.section + 'Show']) ? " ng-show=\"" + this.form[field.section + 'Show'] + "\"" : "";
|
||||
html += "<h3" + sectionShow + ">" + field.section + "</h3>\n";
|
||||
html += "<div" + sectionShow + ">\n";
|
||||
section = field.section;
|
||||
}
|
||||
html += this.buildField(fld, field, options, this.form);
|
||||
}
|
||||
}
|
||||
if (section !== '') {
|
||||
html += "</div>\n</div>\n";
|
||||
}
|
||||
if (group !== '') {
|
||||
html += "</div>\n";
|
||||
}
|
||||
}
|
||||
|
||||
//buttons
|
||||
if (!this.modal) {
|
||||
if (this.has('buttons')) {
|
||||
|
||||
if (this.form.twoColumns) {
|
||||
html += "<div class=\"row\">\n";
|
||||
html += "<div class=\"col-lg-12\">\n";
|
||||
html += "<hr />\n";
|
||||
}
|
||||
|
||||
html += "<div class=\"buttons\" ";
|
||||
html += "id=\"" + this.form.name + "_controls\" ";
|
||||
|
||||
html += ">\n";
|
||||
|
||||
if (this.form.horizontal) {
|
||||
offset = 2;
|
||||
if (this.form.buttons.labelClass) {
|
||||
offset = parseInt(this.form.buttons.labelClass.replace(/[A-Z,a-z,-]/g, ''));
|
||||
}
|
||||
width = 12 - offset;
|
||||
html += "<div class=\"col-lg-offset-" + offset + " col-lg-" + width + ">\n";
|
||||
}
|
||||
|
||||
for (btn in this.form.buttons) {
|
||||
if (typeof this.form.buttons[btn] === 'object') {
|
||||
button = this.form.buttons[btn];
|
||||
|
||||
// Set default color and label for Save and Reset
|
||||
if (btn === 'save') {
|
||||
button.label = 'Save';
|
||||
button['class'] = 'btn-success';
|
||||
}
|
||||
if (btn === 'reset') {
|
||||
button.label = 'Reset';
|
||||
button['class'] = 'btn-default';
|
||||
}
|
||||
|
||||
// Build button HTML
|
||||
html += "<button type=\"button\" ";
|
||||
html += "class=\"btn btn-sm";
|
||||
html += (button['class']) ? " " + button['class'] : "";
|
||||
html += "\" ";
|
||||
html += "id=\"" + this.form.name + "_" + btn + "_btn\" ";
|
||||
|
||||
if (button.ngClick) {
|
||||
html += this.attr(button, 'ngClick');
|
||||
}
|
||||
if (button.ngDisabled) {
|
||||
if (btn !== 'reset') {
|
||||
html += "ng-disabled=\"" + this.form.name + "_form.$pristine || " + this.form.name + "_form.$invalid";
|
||||
html += (this.form.allowReadonly) ? " || " + this.form.name + "ReadOnly == true" : "";
|
||||
html += "\" ";
|
||||
} else {
|
||||
html += "ng-disabled=\"" + this.form.name + "_form.$pristine";
|
||||
html += (this.form.allowReadonly) ? " || " + this.form.name + "ReadOnly == true" : "";
|
||||
html += "\" ";
|
||||
}
|
||||
}
|
||||
html += ">";
|
||||
html += SelectIcon({
|
||||
action: btn
|
||||
});
|
||||
html += " " + button.label + "</button>\n";
|
||||
}
|
||||
}
|
||||
html += "</div><!-- buttons -->\n";
|
||||
|
||||
if (this.form.horizontal) {
|
||||
html += "</div>\n";
|
||||
}
|
||||
|
||||
if (this.form.twoColumns) {
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
html += "</form>\n";
|
||||
|
||||
if (!this.modal && this.has('well')) {
|
||||
if ( !(this.form.collapse && this.form.collapseMode === options.mode)) {
|
||||
html += "</div>\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (this.form.collapse && this.form.collapseMode === options.mode) {
|
||||
html += "</div>\n";
|
||||
//html += "</div>\n";
|
||||
}
|
||||
}
|
||||
|
||||
//buttons
|
||||
if (!this.modal) {
|
||||
if (this.has('buttons')) {
|
||||
|
||||
if (this.form.twoColumns) {
|
||||
html += "<div class=\"row\">\n";
|
||||
html += "<div class=\"col-lg-12\">\n";
|
||||
html += "<hr />\n";
|
||||
}
|
||||
|
||||
html += "<div class=\"buttons\" ";
|
||||
html += "id=\"" + this.form.name + "_controls\" ";
|
||||
|
||||
html += ">\n";
|
||||
|
||||
if (this.form.horizontal) {
|
||||
offset = 2;
|
||||
if (this.form.buttons.labelClass) {
|
||||
offset = parseInt(this.form.buttons.labelClass.replace(/[A-Z,a-z,-]/g, ''));
|
||||
}
|
||||
width = 12 - offset;
|
||||
html += "<div class=\"col-lg-offset-" + offset + " col-lg-" + width + ">\n";
|
||||
}
|
||||
|
||||
for (btn in this.form.buttons) {
|
||||
if (typeof this.form.buttons[btn] === 'object') {
|
||||
button = this.form.buttons[btn];
|
||||
|
||||
// Set default color and label for Save and Reset
|
||||
if (btn === 'save') {
|
||||
button.label = 'Save';
|
||||
button['class'] = 'btn-success';
|
||||
}
|
||||
if (btn === 'reset') {
|
||||
button.label = 'Reset';
|
||||
button['class'] = 'btn-default';
|
||||
}
|
||||
|
||||
// Build button HTML
|
||||
html += "<button type=\"button\" ";
|
||||
html += "class=\"btn btn-sm";
|
||||
html += (button['class']) ? " " + button['class'] : "";
|
||||
html += "\" ";
|
||||
html += "id=\"" + this.form.name + "_" + btn + "_btn\" ";
|
||||
|
||||
if (button.ngClick) {
|
||||
html += this.attr(button, 'ngClick');
|
||||
}
|
||||
if (button.ngDisabled) {
|
||||
if (btn !== 'reset') {
|
||||
html += "ng-disabled=\"" + this.form.name + "_form.$pristine || " + this.form.name + "_form.$invalid";
|
||||
html += (this.form.allowReadonly) ? " || " + this.form.name + "ReadOnly == true" : "";
|
||||
html += "\" ";
|
||||
} else {
|
||||
html += "ng-disabled=\"" + this.form.name + "_form.$pristine";
|
||||
html += (this.form.allowReadonly) ? " || " + this.form.name + "ReadOnly == true" : "";
|
||||
html += "\" ";
|
||||
}
|
||||
}
|
||||
html += ">";
|
||||
html += SelectIcon({
|
||||
action: btn
|
||||
});
|
||||
html += " " + button.label + "</button>\n";
|
||||
}
|
||||
}
|
||||
html += "</div><!-- buttons -->\n";
|
||||
|
||||
if (this.form.horizontal) {
|
||||
html += "</div>\n";
|
||||
}
|
||||
|
||||
if (this.form.twoColumns) {
|
||||
html += "</div>\n";
|
||||
html += "</div>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
html += "</form>\n";
|
||||
|
||||
if (!this.modal && this.has('well')) {
|
||||
if ( !(this.form.collapse && this.form.collapseMode === options.mode)) {
|
||||
html += "</div>\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (this.form.collapse && this.form.collapseMode === options.mode) {
|
||||
html += "</div>\n";
|
||||
//html += "</div>\n";
|
||||
}
|
||||
|
||||
|
||||
if ((!this.modal) && options.related && this.form.related) {
|
||||
html += this.buildCollections(options);
|
||||
}
|
||||
|
||||
@ -470,8 +470,8 @@ angular.module('GeneratorHelpers', ['GeneratorHelpers'])
|
||||
|
||||
// Add collapse/expand icon --used on job_events page
|
||||
if (list.hasChildren && field.hasChildren) {
|
||||
html += "<div class=\"level level-{{ " + list.iterator + ".event_level }}\"><a href=\"\" ng-click=\"{{ " +
|
||||
list.iterator + ".ngclick }}\"> " +
|
||||
html += "<div class=\"level level-{{ " + list.iterator + ".event_level }}\"><a href=\"\" ng-click=\"toggle(" +
|
||||
list.iterator + ".id)\"> " +
|
||||
"<i class=\"{{ " + list.iterator + ".ngicon }}\"></i></a></div>";
|
||||
//ng-show=\"'\{\{ " + list.iterator + ".related.children \}\}' !== ''\"
|
||||
}
|
||||
|
||||
@ -406,13 +406,13 @@ angular.module('ListGenerator', ['GeneratorHelpers'])
|
||||
html += "</tr>\n";
|
||||
|
||||
// Message for when a collection is empty
|
||||
html += "<tr class=\"info\" ng-show=\"" + list.iterator + "Loading == false && " + list.name + ".length == 0\">\n";
|
||||
html += "<td colspan=\"" + cnt + "\">No records matched your search.</td>\n";
|
||||
html += "<tr class=\"loading-info\" ng-show=\"" + list.iterator + "Loading == false && " + list.name + ".length == 0\">\n";
|
||||
html += "<td colspan=\"" + cnt + "\"><div class=\"loading-info\">No records matched your search.</div></td>\n";
|
||||
html += "</tr>\n";
|
||||
|
||||
// Message for loading
|
||||
html += "<tr class=\"info\" ng-show=\"" + list.iterator + "Loading == true\">\n";
|
||||
html += "<td colspan=\"" + cnt + "\">Loading...</td>\n";
|
||||
html += "<tr class=\"loading-info\" ng-show=\"" + list.iterator + "Loading == true\">\n";
|
||||
html += "<td colspan=\"" + cnt + "\"><div class=\"loading-info\">Loading...</div></td>\n";
|
||||
html += "</tr>\n";
|
||||
|
||||
// End List
|
||||
|
||||
@ -22,14 +22,14 @@
|
||||
</script>
|
||||
<script src="{{ STATIC_URL }}js/config.js"></script>
|
||||
<script src="{{ STATIC_URL }}lib/jquery/jquery.min.js"></script>
|
||||
<script src="{{ STATIC_URL }}lib/angular/angular.js"></script>
|
||||
<script src="{{ STATIC_URL }}lib/angular/angular.min.js"></script>
|
||||
<script src="{{ STATIC_URL }}lib/angular-route/angular-route.min.js"></script>
|
||||
<script src="{{ STATIC_URL }}lib/angular-resource/angular-resource.min.js"></script>
|
||||
<script src="{{ STATIC_URL }}lib/angular-cookies/angular-cookies.min.js"></script>
|
||||
<script src="{{ STATIC_URL }}lib/angular-sanitize/angular-sanitize.min.js"></script>
|
||||
<script src="{{ STATIC_URL }}lib/angular-md5/angular-md5.min.js"></script>
|
||||
{% if settings.USE_MINIFIED_JS %}
|
||||
<script src="{{ STATIC_URL }}js/awx-min.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/awx.min.js"></script>
|
||||
{% else %}
|
||||
<script src="{{ STATIC_URL }}lib/less.js/dist/less-1.6.2.min.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/app.js"></script>
|
||||
@ -64,6 +64,7 @@
|
||||
<script src="{{ STATIC_URL }}js/forms/Users.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/forms/Organizations.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/forms/Inventories.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/forms/InventoryStatus.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/forms/Teams.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/forms/Hosts.js"></script>
|
||||
<script src="{{ STATIC_URL }}js/forms/Groups.js"></script>
|
||||
@ -246,7 +247,7 @@
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-target="#form-modal"
|
||||
data-dismiss="modal" aria-hidden="true" ng-click="cancelModal()">×</button>
|
||||
<h3 ng-bind-html-unsafe="formModalHeader"></h3>
|
||||
<h3 ng-bind-html="formModalHeader"></h3>
|
||||
</div>
|
||||
<div class="modal-body" id="form-modal-body"></div>
|
||||
<div class="modal-footer">
|
||||
@ -265,7 +266,7 @@
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-target="#form-modal2"
|
||||
data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 ng-bind-html-unsafe="formModal2Header"></h3>
|
||||
<h3 ng-bind-html="formModal2Header"></h3>
|
||||
</div>
|
||||
<div class="modal-body" id="form-modal2-body"></div>
|
||||
<div class="modal-footer">
|
||||
@ -306,7 +307,7 @@
|
||||
data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 ng-bind="promptHeader" id="prompt-header"></h3>
|
||||
</div>
|
||||
<div class="modal-body" ng-bind-html-unsafe="promptBody" id="prompt-body">
|
||||
<div class="modal-body" ng-bind-html="promptBody" id="prompt-body">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" data-target="#prompt-modal" data-dismiss="modal" id="prompt_cancel_btn" class="btn btn-default">No</a>
|
||||
@ -326,7 +327,7 @@
|
||||
<h3 ng-bind="alertHeader"></h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert" ng-class="alertClass" ng-bind-html-unsafe="alertBody"></div>
|
||||
<div class="alert" ng-class="alertClass" ng-bind-html="alertBody"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" ng-hide="disableButtons" data-target="#form-modal" data-dismiss="modal" id="alert_ok_btn" class="btn btn-primary">OK</a>
|
||||
@ -344,7 +345,7 @@
|
||||
<h3 ng-bind="alertHeader2"></h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert" ng-class="alertClass2" ng-bind-html-unsafe="alertBody2"></div>
|
||||
<div class="alert" ng-class="alertClass2" ng-bind-html="alertBody2"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a href="#" ng-hide="disableButtons2" data-target="#form-modal2" data-dismiss="modal" id="alert2_ok_btn" class="btn btn-primary">OK</a>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user