elements
+ $(this).remove();
+ });
+ $('.popover').each(function () {
+ // remove lingering popover
elements
+ $(this).remove();
+ });
+ $("#configure-jobs").show();
+ $("#configure-schedules-form-container").hide();
+ $('#configure-schedules-list').empty();
+ $('#configure-schedules-form').empty();
+ $('#configure-schedules-detail').empty();
+ $('#configure-tower-dialog').hide();
+ $(this).dialog('destroy');
+ scope.cancelConfigure();
+ },
+ });
+
+
+
+ // Cancel
+ scope.cancelConfigure = function () {
+ try {
+ $('#configure-tower-dialog').dialog('close');
+ }
+ catch(e) {
+ //ignore
+ }
+ if (scope.searchCleanup) {
+ scope.searchCleanup();
+ }
+ // if (!Empty(parent_scope) && parent_scope.restoreSearch) {
+ // parent_scope.restoreSearch();
+ // }
+ else {
+ Wait('stop');
+ }
+ };
+
+ scope.submitJob = function (id) {
+ Wait('start');
+ scheduleUrl += id+'/launch/';
+ CreateDialog({
+ id: 'prompt-for-days' ,
+ title: "Cleanup Job",
+ scope: scope,
+ width: 500,
+ height: 300,
+ minWidth: 200,
+ callback: 'PromptForDays',
+ buttons: [{
+ "label": "Cancel",
+ "onClick": function() {
+ $(this).dialog('close');
+
+ },
+ "icon": "fa-times",
+ "class": "btn btn-default",
+ "id": "prompt-for-days-button"
+ },{
+ "label": "Launch",
+ "onClick": function() {
+ var extra_vars = {"days": $("#days_to_keep").val() },
+ data = {};
+ data.extra_vars = JSON.stringify(extra_vars);
+
+ Rest.setUrl(scheduleUrl);
+ Rest.post(data)
+ .success(function() {
+ Wait('stop');
+ $("#prompt-for-days").dialog("close");
+ $("#configure-tower-dialog").dialog('close');
+ })
+ .error(function(data, status) {
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'Failed updating job ' + scope.job_template_id + ' with variables. PUT returned: ' + status });
+ });
+ },
+ "icon": "fa-rocket",
+ "class": "btn btn-primary",
+ "id": "prompt-for-days-button"
+ }]
+ });
+
+ if (scope.removePromptForDays) {
+ scope.removePromptForDays();
+ }
+ scope.removePromptForDays = scope.$on('PromptForDays', function() {
+ // $('#configure-tower-dialog').dialog('close');
+ $('#prompt-for-days').show();
+ $('#prompt-for-days').dialog('open');
+ Wait('stop');
+ });
+
+
+
+ };
+
+ scope.configureSchedule = function(id, name) {
+ Rest.setUrl(scheduleUrl+id+'/schedules/');
+ Rest.get()
+ .success(function(data) {
+ if(data.count>0){
+ scope.days=data.results[0].extra_data.days;
+ ConfigureTowerSchedule({
+ scope: scope,
+ mode: 'edit',
+ url: scheduleUrl+id+'/schedules/'
+ });
+ } else {
+ ConfigureTowerSchedule({
+ scope: scope,
+ mode: 'add',
+ url: scheduleUrl+id+'/schedules/',
+ name: name
+ });
+ }
+ })
+ .error(function(data, status) {
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'Failed updating job ' + scope.job_template_id + ' with variables. PUT returned: ' + status });
+ });
+
+ };
+
+ scope.addCustomInv = function(){
+ // generator.inject(form, { mode: 'add', related: false, scope: $scope, });
+ generator.inject(form, { id:'configure-jobs', mode: 'add' , scope:scope, related: false, breadCrumbs: false});
+ generator.reset();
+ };
+
+ parent_scope.refreshJobs = function(){
+ scope.search(SchedulesList.iterator);
+ };
+
+ };
+ }])
+
+
+.factory('ConfigureTowerSchedule', ['$compile','SchedulerInit', 'Rest', 'Wait', 'SetSchedulesInnerDialogSize', 'SchedulePost', 'ProcessErrors', 'GetBasePath', 'Empty', 'Prompt',
+function($compile, SchedulerInit, Rest, Wait, SetSchedulesInnerDialogSize, SchedulePost, ProcessErrors, GetBasePath, Empty, Prompt) {
+ return function(params) {
+ var parent_scope = params.scope,
+ mode = params.mode, // 'add' or 'edit'
+ url = params.url,
+ scope = parent_scope.$new(),
+ id = params.id || undefined,
+ name = params.name || undefined,
+ schedule = {},
+ scheduler,
+ target,
+ showForm,
+ list,
+ detail,
+ restoreList,
+ container,
+ elem;
+
+//
+
+ // Wait('start');
+ // detail = $('#schedules-detail').hide();
+ // list = $('#schedules-list');
+ // target = $('#schedules-form');
+ // container = $('#schedules-form-container');
+
+ Wait('start');
+ // $('#configure-jobs').hide();
+ detail = $('#configure-schedules-detail').hide();
+ list = $('#configure-schedules-list');
+ target = $('#configure-schedules-form');
+ container = $('#configure-schedules-form-container');
+ $("#configure-jobs").show();
+ $("#configure-schedules-form-container").hide();
+ scope.mode = mode;
+ // Clean up any lingering stuff
+ container.hide();
+ target.empty();
+ $('.tooltip').each(function () {
+ $(this).remove();
+ });
+ $('.popover').each(function () {
+ $(this).remove();
+ });
+
+ elem = angular.element(document.getElementById('configure-schedules-form-container'));
+ $compile(elem)(scope);
+
+ if (scope.removeScheduleReady) {
+ scope.removeScheduleReady();
+ }
+ scope.removeScheduleReady = scope.$on('ScheduleReady', function() {
+ // Insert the scheduler widget into the hidden div
+ scheduler = SchedulerInit({ scope: scope, requireFutureStartTime: false });
+ scheduler.inject('configure-schedules-form', false);
+ scheduler.injectDetail('configure-schedules-detail', false);
+ scheduler.clear();
+ scope.formShowing = true;
+ scope.showRRuleDetail = false;
+ scope.schedulesTitle = (mode === 'edit') ? 'Edit Schedule' : 'Create Schedule';
+
+
+ // display the scheduler widget
+ showForm = function() {
+ $('#configure-jobs').show('slide', { direction: 'left' }, 500);
+ $('#configure-jobs').hide();
+ Wait('stop');
+ $('#configure-schedules-overlay').width($('#configure-schedules-tab')
+ .width()).height($('#configure-schedules-tab').height()).show();
+ container.width($('#configure-schedules-tab').width() - 18);
+ SetSchedulesInnerDialogSize();
+ container.show('slide', { direction: 'right' }, 300);
+ // scope.schedulerPurgeDays = (!Empty(scope.days)) ? Number(scope.days) : 30;
+ target.show();
+ if(mode==="add"){
+ scope.$apply(function(){
+ scope.schedulerPurgeDays = 30;
+ scope.schedulerName = name+' Schedule';
+ });
+ }
+ if (mode === 'edit') {
+ scope.$apply(function() {
+ scheduler.setRRule(schedule.rrule);
+ scheduler.setName(schedule.name);
+ scope.schedulerPurgeDays = (!Empty(scope.days)) ? Number(scope.days) : 30;
+ });
+ }
+ };
+ setTimeout(function() { showForm(); }, 1000);
+ });
+
+ restoreList = function() {
+ // $('#group-save-button').prop('disabled', false);
+ $('#configure-jobs').show('slide', { direction: 'right' }, 500);
+ // $('#configure-jobs').width($('#configure-jobs').width()).height($('#configure-jobs').height()).hide();
+ // parent_scope.refreshSchedules();
+ list.show('slide', { direction: 'right' }, 500);
+ $('#configure-schedules-overlay').width($('#configure-schedules-tab').width()).height($('#configure-schedules-tab').height()).hide();
+ parent_scope.refreshSchedules();
+
+ };
+
+ scope.showScheduleDetail = function() {
+ if (scope.formShowing) {
+ if (scheduler.isValid()) {
+ detail.width($('#configure-schedules-form').width()).height($('#configure-schedules-form').height());
+ target.hide();
+ detail.show();
+ scope.formShowing = false;
+ }
+ }
+ else {
+ detail.hide();
+ target.show();
+ scope.formShowing = true;
+ }
+ };
+
+ if (scope.removeScheduleSaved) {
+ scope.removeScheduleSaved();
+ }
+ scope.removeScheduleSaved = scope.$on('ScheduleSaved', function() {
+ Wait('stop');
+ container.hide('slide', { direction: 'left' }, 500, restoreList);
+ scope.$destroy();
+ });
+
+ scope.saveScheduleForm = function() {
+ var extra_vars;
+ if (scheduler.isValid()) {
+ scope.schedulerIsValid = true;
+ url = (mode==="edit") ? GetBasePath('schedules')+id+'/' : url;
+
+ extra_vars = {
+ "days" : scope.scheduler_form.schedulerPurgeDays.$viewValue
+ };
+ schedule.extra_data = JSON.stringify(extra_vars);
+
+ SchedulePost({
+ scope: scope,
+ url: url,
+ scheduler: scheduler,
+ callback: 'ScheduleSaved',
+ mode: mode,
+ schedule: schedule
+ });
+ }
+ else {
+ scope.schedulerIsValid = false;
+ }
+ };
+
+ scope.deleteSystemSchedule = function(){
+ var hdr = 'Delete Schedule',
+ action = function () {
+ Wait('start');
+ Rest.setUrl(schedule.url);
+ Rest.destroy()
+ .success(function () {
+ $('#prompt-modal').modal('hide');
+ Wait('stop');
+ // scope.$emit(callback, id);
+ scope.cancelScheduleForm();
+ })
+ .error(function (data, status) {
+ try {
+ $('#prompt-modal').modal('hide');
+ }
+ catch(e) {
+ // ignore
+ }
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!', msg: 'Call to ' + url +
+ ' failed. DELETE returned: ' + status });
+ });
+ };
+
+ Prompt({
+ hdr: hdr,
+ body: "
Are you sure you want to delete the " + scope.schedulerName + " schedule?
",
+ action: action,
+ backdrop: false
+ });
+ // }
+ // } else {
+ // //a schedule doesn't exist
+ // $("#prompt_action_btn").text('OK');
+ // $('#prompt_cancel_btn').hide();
+ // var action2 = function(){
+ // $('#prompt-modal').modal('hide');
+ // $("#prompt_action_btn").text('Yes');
+ // $('#prompt_cancel_btn').show();
+ // };
+ // Prompt({
+ // hdr: "Delete",
+ // body: "
No schedule exists for that job.
",
+ // action: action2,
+ // backdrop: false
+ // });
+ // }
+ // })
+ // .error(function(data, status) {
+ // ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ // msg: 'Failed updating job ' + scope.job_template_id + ' with variables. PUT returned: ' + status });
+ // });
+ };
+
+ scope.cancelScheduleForm = function() {
+ container.hide('slide', { direction: 'right' }, 500, restoreList);
+ scope.$destroy();
+ };
+
+ if (mode === 'edit') {
+ // Get the existing record
+ Rest.setUrl(url); //GetBasePath('schedules')+id+'/');
+ Rest.get()
+ .success(function(data) {
+ schedule = data.results[0];
+ id = schedule.id;
+ if (!/DTSTART/.test(schedule.rrule)) {
+ schedule.rrule += ";DTSTART=" + schedule.dtstart.replace(/\.\d+Z$/,'Z');
+ }
+ schedule.rrule = schedule.rrule.replace(/ RRULE:/,';');
+ schedule.rrule = schedule.rrule.replace(/DTSTART:/,'DTSTART=');
+ scope.$emit('ScheduleReady');
+ })
+ .error(function(data,status){
+ ProcessErrors(scope, data, status, null, { hdr: 'Error!',
+ msg: 'Failed to get: ' + url + ' GET returned: ' + status });
+ });
+ }
+ else {
+ scope.$emit('ScheduleReady');
+ }
+ };
+}]);
diff --git a/awx/ui/static/js/lists/CustomInventory.js b/awx/ui/static/js/lists/CustomInventory.js
new file mode 100644
index 0000000000..e6d0d61cdc
--- /dev/null
+++ b/awx/ui/static/js/lists/CustomInventory.js
@@ -0,0 +1,79 @@
+/*********************************************
+ * Copyright (c) 2014 AnsibleWorks, Inc.
+ *
+ * Credentials.js
+ * List view object for Credential data model.
+ *
+ * @dict
+ */
+
+'use strict';
+
+angular.module('CustomInventoryListDefinition', [])
+ .value('CustomInventoryList', {
+
+ name: 'custum_inventories',
+ iterator: 'custom_inventory',
+ selectTitle: 'Add custom inventory',
+ editTitle: 'Custom Inventories',
+ selectInstructions: "
Select existing credentials by clicking each credential or checking the related checkbox. When " +
+ "finished, click the blue Select button, located bottom right.
Create a brand new credential by clicking " +
+ "the button.
",
+ index: false,
+ hover: true,
+
+ fields: {
+ name: {
+ key: true,
+ label: 'Name',
+ columnClass: 'col-md-3 col-sm-9 col-xs-9',
+ modalColumnClass: 'col-md-8'
+ },
+ description: {
+ label: 'Description',
+ excludeModal: true,
+ columnClass: 'col-md-5 hidden-sm hidden-xs'
+ },
+ // kind: {
+ // label: 'Type',
+ // searchType: 'select',
+ // searchOptions: [], // will be set by Options call to credentials resource
+ // excludeModal: true,
+ // nosort: true,
+ // columnClass: 'col-md-3 hidden-sm hidden-xs'
+ // }
+ },
+
+ actions: {
+ add: {
+ mode: 'all', // One of: edit, select, all
+ ngClick: 'addCustomInv()',
+ awToolTip: 'Create a new credential'
+ },
+ stream: {
+ ngClick: "showActivity()",
+ awToolTip: "View Activity Stream",
+ mode: 'edit'
+ }
+ },
+
+ fieldActions: {
+ edit: {
+ ngClick: "editCredential(credential.id)",
+ icon: 'fa-edit',
+ label: 'Edit',
+ "class": 'btn-sm',
+ awToolTip: 'Edit credential',
+ dataPlacement: 'top'
+ },
+
+ "delete": {
+ ngClick: "deleteCredential(credential.id, credential.name)",
+ icon: 'fa-trash',
+ label: 'Delete',
+ "class": 'btn-sm',
+ awToolTip: 'Delete credential',
+ dataPlacement: 'top'
+ }
+ }
+ });
diff --git a/awx/ui/templates/ui/index.html b/awx/ui/templates/ui/index.html
index f39a2b8373..66dbd1b8a4 100644
--- a/awx/ui/templates/ui/index.html
+++ b/awx/ui/templates/ui/index.html
@@ -89,6 +89,7 @@
+
@@ -114,6 +115,7 @@
+
@@ -133,6 +135,7 @@
+
@@ -196,8 +199,9 @@
About Tower
Account Settings
-
Configure Tower
Contact Support
+
Inventory Script
+
Management Jobs
Monitor Tower
Portal Mode
View License
@@ -237,8 +241,9 @@