Files
awx/awx/ui/static/js/helpers/Schedules.js
T
Jared Tabor d7e2614760 Copyright JS files and removing unlicensed files
Adding the Copyright and All Rights Reserved to the JS files, as well as removing pwdmeter and 3dDonut chart (in lieu of d3.js donut chart)

adding the legend and getting pie chart to donut

adding data labels to donut chart

working legend and tooltip

job detail donut

Ansible Copyright added to beginning of all JS files

removing pwdmeter and d3donut

fixing merge conflicts
2015-05-29 12:08:22 -04:00

632 lines
25 KiB
JavaScript

/*************************************************
* Copyright (c) 2015 Ansible, Inc.
*
* All Rights Reserved
*************************************************/
/**
* @ngdoc function
* @name helpers.function:Schedules
* @description
* Schedules Helper
*
* Display the scheduler widget in a dialog
*
*/
import listGenerator from 'tower/shared/list-generator/main';
export default
angular.module('SchedulesHelper', [ 'Utilities', 'RestServices', 'SchedulesHelper', 'SearchHelper', 'PaginationHelpers', listGenerator.name, 'ModalDialog',
'GeneratorHelpers'])
.factory('ShowSchedulerModal', ['Wait', 'CreateDialog', function(Wait, CreateDialog) {
return function(params) {
// Set modal dimensions based on viewport width
var buttons,
scope = params.scope,
callback = params.callback;
buttons = [{
"label": "Cancel",
"onClick": function() {
$(this).dialog('close');
},
"icon": "fa-times",
"class": "btn btn-default",
"id": "schedule-close-button"
},{
"label": "Save",
"onClick": function() {
setTimeout(function(){
scope.$apply(function(){
scope.saveSchedule();
});
});
},
"icon": "fa-check",
"class": "btn btn-primary",
"id": "schedule-save-button"
}];
CreateDialog({
id: 'scheduler-modal-dialog',
scope: scope,
buttons: buttons,
width: 700,
height: 725,
minWidth: 400,
onClose: function() {
$('#scheduler-modal-dialog #form-container').empty();
},
onOpen: function() {
Wait('stop');
$('#scheduler-tabs a:first').tab('show');
$('#schedulerName').focus();
$('#rrule_nlp_description').dblclick(function() {
setTimeout(function() { scope.$apply(function() { scope.showRRule = (scope.showRRule) ? false : true; }); }, 100);
});
},
callback: callback
});
};
}])
.factory('EditSchedule', ['SchedulerInit', 'ShowSchedulerModal', 'Wait', 'Rest', 'ProcessErrors', 'GetBasePath', 'SchedulePost',
function(SchedulerInit, ShowSchedulerModal, Wait, Rest, ProcessErrors, GetBasePath, SchedulePost) {
return function(params) {
var scope = params.scope,
id = params.id,
callback = params.callback,
schedule, scheduler,
url = GetBasePath('schedules') + id + '/';
if (scope.removeDialogReady) {
scope.removeDialogReady();
}
scope.removeDialogReady = scope.$on('DialogReady', function() {
$('#scheduler-modal-dialog').dialog('open');
$('#schedulerName').focus();
setTimeout(function() {
scope.$apply(function() {
scheduler.setRRule(schedule.rrule);
scheduler.setName(schedule.name);
});
}, 300);
});
if (scope.removeScheduleFound) {
scope.removeScheduleFound();
}
scope.removeScheduleFound = scope.$on('ScheduleFound', function() {
$('#form-container').empty();
scheduler = SchedulerInit({ scope: scope, requireFutureStartTime: false });
scheduler.inject('form-container', false);
scheduler.injectDetail('occurrences', false);
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=');
ShowSchedulerModal({ scope: scope, callback: 'DialogReady' });
scope.showRRuleDetail = false;
});
if (scope.removeScheduleSaved) {
scope.removeScheduleSaved();
}
scope.removeScheduleSaved = scope.$on('ScheduleSaved', function() {
Wait('stop');
$('#scheduler-modal-dialog').dialog('close');
if (callback) {
scope.$emit(callback);
}
});
scope.saveSchedule = function() {
$('#scheduler-tabs a:first').tab('show');
SchedulePost({
scope: scope,
url: url,
scheduler: scheduler,
callback: 'ScheduleSaved',
mode: 'edit',
schedule: schedule
});
};
$('#scheduler-tabs li a').on('shown.bs.tab', function(e) {
if ($(e.target).text() === 'Details') {
if (!scheduler.isValid()) {
$('#scheduler-tabs a:first').tab('show');
}
}
});
Wait('start');
// Get the existing record
Rest.setUrl(url);
Rest.get()
.success(function(data) {
schedule = data;
scope.$emit('ScheduleFound');
})
.error(function(data,status){
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve schedule ' + id + ' GET returned: ' + status });
});
};
}])
.factory('AddSchedule', ['$location', '$routeParams', 'SchedulerInit', 'ShowSchedulerModal', 'Wait', 'GetBasePath', 'Empty',
'SchedulePost',
function($location, $routeParams, SchedulerInit, ShowSchedulerModal, Wait, GetBasePath, Empty, SchedulePost) {
return function(params) {
var scope = params.scope,
callback= params.callback,
base = $location.path().replace(/^\//, '').split('/')[0],
url = GetBasePath(base),
scheduler;
if (!Empty($routeParams.template_id)) {
url += $routeParams.template_id + '/schedules/';
}
else if (!Empty($routeParams.id)) {
url += $routeParams.id + '/schedules/';
}
if (scope.removeDialogReady) {
scope.removeDialogReady();
}
scope.removeDialogReady = scope.$on('DialogReady', function() {
$('#scheduler-modal-dialog').dialog('open');
$('#schedulerName').focus();
});
Wait('start');
$('#form-container').empty();
scheduler = SchedulerInit({ scope: scope, requireFutureStartTime: false });
scheduler.inject('form-container', false);
scheduler.injectDetail('occurrences', false);
scheduler.clear();
ShowSchedulerModal({ scope: scope, callback: 'DialogReady' });
scope.showRRuleDetail = false;
if (scope.removeScheduleSaved) {
scope.removeScheduleSaved();
}
scope.removeScheduleSaved = scope.$on('ScheduleSaved', function() {
Wait('stop');
$('#scheduler-modal-dialog').dialog('close');
if (callback) {
scope.$emit(callback);
}
});
scope.saveSchedule = function() {
$('#scheduler-tabs a:first').tab('show');
SchedulePost({
scope: scope,
url: url,
scheduler: scheduler,
callback: 'ScheduleSaved',
mode: 'add'
});
};
$('#scheduler-tabs li a').on('shown.bs.tab', function(e) {
if ($(e.target).text() === 'Details') {
if (!scheduler.isValid()) {
$('#scheduler-tabs a:first').tab('show');
}
}
});
};
}])
.factory('SchedulePost', ['Rest', 'ProcessErrors', 'RRuleToAPI', 'Wait', function(Rest, ProcessErrors, RRuleToAPI, Wait) {
return function(params) {
var scope = params.scope,
url = params.url,
scheduler = params.scheduler,
mode = params.mode,
schedule = (params.schedule) ? params.schedule : {},
callback = params.callback,
newSchedule, rrule;
if (scheduler.isValid()) {
Wait('start');
newSchedule = scheduler.getValue();
rrule = scheduler.getRRule();
schedule.name = newSchedule.name;
schedule.rrule = RRuleToAPI(rrule.toString());
schedule.description = (/error/.test(rrule.toText())) ? '' : rrule.toText();
Rest.setUrl(url);
if (mode === 'add') {
Rest.post(schedule)
.success(function(){
if (callback) {
scope.$emit(callback);
}
else {
Wait('stop');
}
})
.error(function(data, status){
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'POST to ' + url + ' returned: ' + status });
});
}
else {
Rest.put(schedule)
.success(function(){
if (callback) {
scope.$emit(callback);
}
else {
Wait('stop');
}
})
.error(function(data, status){
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'POST to ' + url + ' returned: ' + status });
});
}
}
else {
return false;
}
};
}])
/**
* Inject the scheduler_dialog.html wherever needed
*/
.factory('LoadDialogPartial', ['Rest', '$compile', 'ProcessErrors', function(Rest, $compile, ProcessErrors) {
return function(params) {
var scope = params.scope,
element_id = params.element_id,
callback = params.callback,
url;
// Add the schedule_dialog.html partial
url = '/static/partials/schedule_dialog.html';
Rest.setUrl(url);
Rest.get()
.success(function(data) {
var e = angular.element(document.getElementById(element_id));
e.append(data);
$compile(e)(scope);
scope.$emit(callback);
})
.error(function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Call to ' + url + ' failed. GET returned: ' + status });
});
};
}])
/**
* Flip a schedule's enable flag
*
* ToggleSchedule({
* scope: scope,
* id: schedule.id to update
* callback: scope.$emit label to call when update completes
* });
*
*/
.factory('ToggleSchedule', ['Wait', 'GetBasePath', 'ProcessErrors', 'Rest', function(Wait, GetBasePath, ProcessErrors, Rest) {
return function(params) {
var scope = params.scope,
id = params.id,
callback = params.callback,
url = GetBasePath('schedules') + id +'/';
// Perform the update
if (scope.removeScheduleFound) {
scope.removeScheduleFound();
}
scope.removeScheduleFound = scope.$on('ScheduleFound', function(e, data) {
data.enabled = (data.enabled) ? false : true;
Rest.put(data)
.success( function() {
if (callback) {
scope.$emit(callback, id);
}
else {
Wait('stop');
}
})
.error( function(data, status) {
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to update schedule ' + id + ' PUT returned: ' + status });
});
});
Wait('start');
// Get the schedule
Rest.setUrl(url);
Rest.get()
.success(function(data) {
scope.$emit('ScheduleFound', data);
})
.error(function(data,status){
ProcessErrors(scope, data, status, null, { hdr: 'Error!',
msg: 'Failed to retrieve schedule ' + id + ' GET returned: ' + status });
});
};
}])
/**
* Delete a schedule. Prompts user to confirm delete
*
* DeleteSchedule({
* scope: $scope containing list of schedules
* id: id of schedule to delete
* callback: $scope.$emit label to call when delete is completed
* })
*
*/
.factory('DeleteSchedule', ['GetBasePath','Rest', 'Wait', 'ProcessErrors', 'Prompt', 'Find',
function(GetBasePath, Rest, Wait, ProcessErrors, Prompt, Find) {
return function(params) {
var scope = params.scope,
id = params.id,
callback = params.callback,
action, schedule, list, url, hdr;
if (scope.schedules) {
list = scope.schedules;
}
else if (scope.scheduled_jobs) {
list = scope.scheduled_jobs;
}
url = GetBasePath('schedules') + id + '/';
schedule = Find({list: list, key: 'id', val: id });
hdr = 'Delete Schedule';
action = function () {
Wait('start');
Rest.setUrl(url);
Rest.destroy()
.success(function () {
$('#prompt-modal').modal('hide');
scope.$emit(callback, id);
})
.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: "<div class=\"alert alert-info\">Are you sure you want to delete the <em>" + schedule.name + "</em> schedule?</div>",
action: action,
backdrop: false
});
};
}])
/**
* Convert rrule string to an API agreeable format
*
*/
.factory('RRuleToAPI', [ function() {
return function(rrule) {
var response;
response = rrule.replace(/(^.*(?=DTSTART))(DTSTART=.*?;)(.*$)/, function(str, p1, p2, p3) {
return p2.replace(/\;/,'').replace(/=/,':') + ' ' + 'RRULE:' + p1 + p3;
});
return response;
};
}])
.factory('SchedulesControllerInit', ['$location', 'ToggleSchedule', 'DeleteSchedule', 'EditSchedule', 'AddSchedule',
function($location, ToggleSchedule, DeleteSchedule, EditSchedule, AddSchedule) {
return function(params) {
var scope = params.scope,
parent_scope = params.parent_scope,
iterator = (params.iterator) ? params.iterator : scope.iterator,
base = $location.path().replace(/^\//, '').split('/')[0];
scope.toggleSchedule = function(event, id) {
try {
$(event.target).tooltip('hide');
}
catch(e) {
// ignore
}
ToggleSchedule({
scope: scope,
id: id,
callback: 'SchedulesRefresh'
});
};
scope.deleteSchedule = function(id) {
DeleteSchedule({
scope: scope,
id: id,
callback: 'SchedulesRefresh'
});
};
scope.editSchedule = function(id) {
EditSchedule({
scope: scope,
id: id,
callback: 'SchedulesRefresh'
});
};
scope.addSchedule = function() {
AddSchedule({
scope: scope,
callback: 'SchedulesRefresh'
});
};
scope.refreshSchedules = function() {
if (base === 'jobs') {
parent_scope.refreshJobs();
}
else {
scope.search(iterator);
}
};
if (scope.removeSchedulesRefresh) {
scope.removeSchedulesRefresh();
}
scope.$on('SchedulesRefresh', function() {
scope.search(iterator);
});
};
}])
.factory('SchedulesListInit', [ function() {
return function(params) {
var scope = params.scope,
list = params.list,
choices = params.choices;
scope[list.name].forEach(function(item, item_idx) {
var fld,
field,
itm = scope[list.name][item_idx],
job = item.summary_fields.unified_job_template;
itm.enabled = (itm.enabled) ? true : false;
if (itm.enabled) {
itm.play_tip = 'Schedule is active. Click to stop.';
itm.status = 'active';
itm.status_tip = 'Schedule is active. Click to stop.';
}
else {
itm.play_tip = 'Schedule is stopped. Click to activate.';
itm.status = 'stopped';
itm.status_tip = 'Schedule is stopped. Click to activate.';
}
itm.nameTip = item.name;
// include the word schedule if the schedule name does not include the word schedule
if (item.name.indexOf("schedule") === -1 && item.name.indexOf("Schedule") === -1) {
itm.nameTip += " schedule";
}
itm.nameTip += " for ";
if (job.name.indexOf("job") === -1 && job.name.indexOf("Job") === -1) {
itm.nameTip += "job ";
}
itm.nameTip += job.name;
itm.nameTip += ". Click to edit schedule.";
// Copy summary_field values
for (field in list.fields) {
fld = list.fields[field];
if (fld.sourceModel) {
if (itm.summary_fields[fld.sourceModel]) {
itm[field] = itm.summary_fields[fld.sourceModel][fld.sourceField];
}
}
}
// Set the item type label
if (list.fields.type) {
choices.every(function(choice) {
if (choice.value === item.type) {
itm.type_label = choice.label;
return false;
}
return true;
});
}
});
};
}])
/**
*
* Called from a controller to setup the scope for a schedules list
*
*/
.factory('LoadSchedulesScope', ['$compile', '$location', '$routeParams','SearchInit', 'PaginateInit', 'generateList', 'SchedulesControllerInit',
'SchedulesListInit',
function($compile, $location, $routeParams, SearchInit, PaginateInit, GenerateList, SchedulesControllerInit, SchedulesListInit) {
return function(params) {
var parent_scope = params.parent_scope,
scope = params.scope,
list = params.list,
id = params.id,
url = params.url,
searchSize = params.searchSize,
pageSize = params.pageSize || 5,
spinner = (params.spinner === undefined) ? true : params.spinner;
GenerateList.inject(list, {
mode: 'edit',
id: id,
breadCrumbs: false,
scope: scope,
searchSize: (searchSize) ? searchSize : 'col-lg-6 col-md-6 col-sm-6 col-xs-12',
showSearch: true
});
SearchInit({
scope: scope,
set: list.name,
list: list,
url: url
});
PaginateInit({
scope: scope,
list: list,
url: url,
pageSize: pageSize
});
scope.iterator = list.iterator;
if (scope.removePostRefresh) {
scope.removePostRefresh();
}
scope.$on('PostRefresh', function(){
SchedulesControllerInit({
scope: scope,
parent_scope: parent_scope,
list: list
});
SchedulesListInit({
scope: scope,
list: list,
choices: parent_scope.type_choices
});
parent_scope.$emit('listLoaded');
});
if ($routeParams.id__int) {
scope[list.iterator + 'SearchField'] = 'id';
scope[list.iterator + 'SearchValue'] = $routeParams.id__int;
scope[list.iterator + 'SearchFieldLabel'] = 'ID';
}
scope.search(list.iterator, null, null, null, null, spinner);
};
}]);