diff --git a/app.js b/app.js
index c496138..e6c6a7d 100755
--- a/app.js
+++ b/app.js
@@ -3,6 +3,7 @@ var app = express();
var crontab = require("./crontab");
var restore = require("./restore");
+var moment = require('moment');
var path = require('path');
var mime = require('mime');
var fs = require('fs');
@@ -30,15 +31,24 @@ app.set('views', __dirname + '/views');
//set port
app.set('port', (process.env.PORT || 8000));
+app.set('listen', (process.env.LISTEN || '0.0.0.0'));
app.get(routes.root, function(req, res) {
// get all the crontabs
crontab.crontabs( function(docs){
- res.render('index', {
- routes : JSON.stringify(routes),
- crontabs : JSON.stringify(docs),
- backups : crontab.get_backup_names(),
- env : crontab.get_env()
+ crontab.templates(function(templates) {
+ res.render('index', {
+ routes : JSON.stringify(routes),
+ crontabs : JSON.stringify(docs),
+ templates: templates,
+ templatesById: templates.reduce(function(memo, t) {
+ memo[t._id] = t;
+ return memo;
+ }, {}),
+ backups : crontab.get_backup_names(),
+ env : crontab.get_env(),
+ moment: moment,
+ });
});
});
})
@@ -46,15 +56,33 @@ app.get(routes.root, function(req, res) {
app.post(routes.save, function(req, res) {
// new job
if(req.body._id == -1){
- crontab.create_new(req.body.name, req.body.command, req.body.schedule, req.body.logging);
+ crontab.create_new(req.body.name, req.body.command, req.body.command_template, req.body.vars, req.body.schedule, req.body.logging);
}
// edit job
else{
+
crontab.update(req.body);
}
res.end();
})
+app.post(routes.save_template, function(req, res) {
+ // new job
+ if(req.body._id == -1){
+ crontab.create_new_template(req.body.name, req.body.command, req.body.schedule);
+ }
+ // edit job
+ else{
+ crontab.update_template(req.body);
+ }
+ res.end();
+});
+
+app.post(routes.remove_template, function(req, res) {
+ crontab.remove_template(req.body._id);
+ res.end();
+})
+
app.post(routes.stop, function(req, res) {
crontab.status(req.body._id, true);
res.end();
@@ -81,11 +109,18 @@ app.get(routes.backup, function(req, res) {
app.get(routes.restore, function(req, res) {
// get all the crontabs
- restore.crontabs(req.query.db, function(docs){
+ restore.loadBackupFile(req.query.db, function(docs, templates) {
res.render('restore', {
routes : JSON.stringify(routes),
crontabs : JSON.stringify(docs),
+ templates: templates,
+ templatesById: templates.reduce(function(memo, t) {
+ memo[t._id] = t;
+ return memo;
+ }, {}),
backups : crontab.get_backup_names(),
+ env : crontab.get_env(),
+ moment: moment,
db: req.query.db
});
});
@@ -102,31 +137,30 @@ app.get(routes.restore_backup, function(req, res) {
})
app.get(routes.export, function(req, res) {
- var file = __dirname + '/crontabs/crontab.db';
+ var backupData = crontab.backup_data();
- var filename = path.basename(file);
- var mimetype = mime.lookup(file);
+ res.setHeader('Content-disposition', 'attachment; filename=crontab_ui_backup.json');
+ res.setHeader('Content-type', 'application/json');
- res.setHeader('Content-disposition', 'attachment; filename=' + filename);
- res.setHeader('Content-type', mimetype);
-
- var filestream = fs.createReadStream(file);
- filestream.pipe(res);
-})
+ res.end(JSON.stringify(backupData));
+});
app.post(routes.import, function(req, res) {
var fstream;
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
- fstream = fs.createWriteStream(__dirname + '/crontabs/crontab.db');
- file.pipe(fstream);
- fstream.on('close', function () {
+
+ file.on('data', function(data) {
+ crontab.restore_data(JSON.parse(data.toString('utf8')));
crontab.reload_db();
- res.redirect(routes.root);
- });
- });
-})
+ });
+ });
+
+ req.busboy.on('finish', function() {
+ res.redirect(routes.root);
+ })
+});
app.get(routes.import_crontab, function(req, res) {
crontab.import_crontab()
@@ -142,6 +176,8 @@ app.get(routes.logger, function(req, res) {
res.end("No errors logged yet");
})
-app.listen(app.get('port'), function() {
- console.log("Crontab UI is running at localhost:" + app.get('port'))
+// app.use('/scripts/moment.js', express.static(__dirname + '/node_modules/moment/min/moment.min.js'));
+
+app.listen(app.get('port'), app.get('listen'), function() {
+ console.log("Crontab UI is running at " + app.get('listen') + ":" + app.get('port'))
})
diff --git a/crontab.js b/crontab.js
index 5401850..6edda46 100644
--- a/crontab.js
+++ b/crontab.js
@@ -1,21 +1,29 @@
//load database
+
+exports.crontab_db_file = __dirname + '/crontabs/crontab.db';
+exports.templates_db_file = __dirname + '/crontabs/templates.db';
+
var Datastore = require('nedb');
-var db = new Datastore({ filename: __dirname + '/crontabs/crontab.db' });
-db.loadDatabase(function (err) {
-});
+var db = {
+ crontabs: new Datastore({ filename: exports.crontab_db_file, autoload: true }),
+ templates: new Datastore({ filename: exports.templates_db_file, autoload: true }),
+};
var exec = require('child_process').exec;
var fs = require('fs');
var cron_parser = require("cron-parser")
var os = require("os")
+var _ = require('underscore');
exports.log_folder = __dirname + '/crontabs/logs';
exports.env_file = __dirname + '/crontabs/env.db';
-crontab = function(name, command, schedule, stopped, logging){
+crontab = function(name, command, command_template, vars, schedule, stopped, logging){
var data = {};
data.name = name;
data.command = command;
+ data.command_template = command_template;
data.schedule = schedule;
+ data.vars = vars || {};
if(stopped != null) {
data.stopped = stopped;
}
@@ -24,34 +32,88 @@ crontab = function(name, command, schedule, stopped, logging){
return data;
}
-exports.create_new = function(name, command, schedule, logging){
- var tab = crontab(name, command, schedule, false, logging);
+crontab_template = function(name, command, schedule){
+ var data = {};
+ data.name = name;
+ data.command = command;
+ data.schedule = schedule;
+ data.timestamp = (new Date()).toString();
+ return data;
+}
+
+exports.create_new = function(name, command, command_template, vars, schedule, logging){
+ var tab = crontab(name, command, command_template, vars, schedule, false, logging);
tab.created = new Date().valueOf();
- db.insert(tab);
+ db.crontabs.insert(tab);
}
exports.update = function(data){
- db.update({_id: data._id}, crontab(data.name, data.command, data.schedule, null, data.logging));
+ db.crontabs.update({_id: data._id}, crontab(data.name, data.command, data.command_template, data.vars, data.schedule, null, data.logging));
}
exports.status = function(_id, stopped){
- db.update({_id: _id},{$set: {stopped: stopped}});
+ db.crontabs.update({_id: _id},{$set: {stopped: stopped}});
}
exports.remove = function(_id){
- db.remove({_id: _id}, {});
-}
-exports.crontabs = function(callback){
- db.find({}).sort({ created: -1 }).exec(function(err, docs){
- for(var i=0; i
');
+
+ $input.change(function() {
+ current_job.vars = current_job.vars || {};
+ current_job.vars[varName] = $(this).val();
+ })
+ })
+
+ } else {
+ job_command = $('#job-command').val();
+ }
+
+ job_string();
+}
+
+function findCommandVariables (command) {
+ return command.match(/{[a-zA-Z]+}/g).map(function(cmd) {
+ return cmd.substring(1, cmd.length - 1);
+ });
+};
+
+function renderTemplateCommand(templateId) {
+ var template = findTemplate(templateId);
+
+ if(template) {
+ return template.command;
+ }
+
+ return '';
+}
+
function newJob(){
+ current_job = {};
schedule = ""
job_command = ""
$("#job-minute").val("*");
@@ -101,14 +168,17 @@ function newJob(){
$("#job").modal("show");
$("#job-name").val("");
$("#job-command").val("");
+ $("#job-command-template").val("");
job_string();
$("#job-save").unbind("click"); // remove existing events attached to this
$("#job-save").click(function(){
// TODO good old boring validations
- $.post(routes.save, {name: $("#job-name").val(), command: job_command , schedule: schedule, _id: -1, logging: $("#job-logging").prop("checked")}, function(){
+ $.post(routes.save, {name: $("#job-name").val(), command: job_command , schedule: schedule, _id: -1, logging: $("#job-logging").prop("checked"), command_template: $('#job-command-template').val(), vars: current_job.vars }, function(){
location.reload();
})
});
+
+ setTemplateVariables(null);
}
function doBackup(){
@@ -145,6 +215,7 @@ function import_db(){
// script corresponding to job popup management
var schedule = "";
var job_command = "";
+var current_job = null;
function job_string(){
$("#job-string").val(schedule + " " + job_command);
return schedule + " " + job_command;
@@ -155,3 +226,83 @@ function set_schedule(){
job_string();
}
// popup management ends
+
+
+/**************** Template Action s***************/
+
+function newTemplate(){
+ schedule = ""
+ template_command = ""
+ $("#template-minute").val("*");
+ $("#template-hour").val("*");
+ $("#template-day").val("*");
+ $("#template-month").val("*");
+ $("#template-week").val("*");
+
+ $("#template-popup").modal("show");
+ $("#template-name").val("");
+ $("#template-command").val("");
+ template_string();
+ $("#template-save").unbind("click"); // remove existing events attached to this
+ $("#template-save").click(function(){
+ // TODO good old boring validations
+ $.post(routes.save_template, {name: $("#template-name").val(), command: template_command , schedule: schedule, _id: -1}, function(){
+ location.reload();
+ })
+ });
+
+ $('#template-remove').unbind('click').hide();
+}
+
+function editTemplate(_id){
+ var template = findTemplate(_id);
+ if(template){
+ $("#template-popup").modal("show");
+ $("#template-name").val(template.name);
+ $("#template-command").val(template.command);
+
+ // if macro not used
+ if(template.schedule && template.schedule.indexOf("@") != 0){
+ var components = template.schedule.split(" ");
+ $("#template-minute").val(components[0]);
+ $("#template-hour").val(components[1]);
+ $("#template-day").val(components[2]);
+ $("#template-month").val(components[3]);
+ $("#template-week").val(components[4]);
+ }
+ schedule = template.schedule;
+ template_command = template.command;
+
+ template_string();
+ }
+
+ $("#template-save").unbind("click"); // remove existing events attached to this
+ $("#template-save").click(function(){
+ // TODO good old boring validations
+ $.post(routes.save_template, {name: $("#template-name").val(), command: template_command , schedule: schedule, _id: _id}, function(){
+ location.reload();
+ })
+ });
+
+ $('#template-remove')
+ .show()
+ .unbind('click')
+ .click(function() {
+ if(window.confirm('Are you sure you want to delete this template?')) {
+ $.post(routes.remove_template, {_id:_id}, function() {
+ location.reload();
+ });
+ }
+ });
+
+}
+
+function set_template_schedule(){
+ schedule = $("#template-minute").val() + " " +$("#template-hour").val() + " " +$("#template-day").val() + " " +$("#template-month").val() + " " +$("#template-week").val();
+ template_string();
+}
+
+function template_string(){
+ $("#template-string").val(schedule + " " + template_command);
+ return schedule + " " + template_command;
+}
diff --git a/restore.js b/restore.js
index 637fe41..91348cd 100644
--- a/restore.js
+++ b/restore.js
@@ -3,15 +3,34 @@ var Datastore = require('nedb');
var exec = require('child_process').exec;
var fs = require('fs');
+var tmp = require('tmp');
-exports.crontabs = function(db_name, callback){
- var db = new Datastore({ filename: __dirname + '/crontabs/' + db_name });
- db.loadDatabase(function (err) {
- });
- db.find({}).sort({ created: -1 }).exec(function(err, docs){
- callback(docs);
- });
-}
+exports.loadBackupFile = function(db_name, callback) {
+
+ console.log(__dirname + '/crontabs/' + db_name);
+
+ var backupFileData = fs.readFileSync(__dirname + '/crontabs/' + db_name).toString('utf8');
+ console.log(backupFileData);
+ var data = JSON.parse(backupFileData);
+
+
+ var crontabFile = tmp.fileSync();
+ var templateFile = tmp.fileSync();
+
+ fs.writeFileSync(crontabFile.name, data.crontabs);
+ fs.writeFileSync(templateFile.name, data.templates);
+
+ var crontabDB = new Datastore({ filename: crontabFile.name , autoload: true });
+ var templateDB = new Datastore({ filename: templateFile.name , autoload: true });
+
+ crontabDB.find({}).sort({ created: -1 }).exec(function(err, docs){
+ templateDB.find({}).sort({ name: 1 }).exec(function(err, templates) {
+
+ callback(docs, templates);
+ })
+ });
+
+};
exports.delete = function(db_name){
fs.unlink(__dirname + '/crontabs/' + db_name);
diff --git a/routes.js b/routes.js
index 15a629c..3dd9a56 100644
--- a/routes.js
+++ b/routes.js
@@ -13,4 +13,6 @@ exports.routes = {
"import": "/import", // this is import from database
"import_crontab": "/import_crontab", // this is from existing crontab
"logger": "/logger",
+ "save_template" : "/save_template",
+ "remove_template" : "/remove_template",
}
diff --git a/views/index.ejs b/views/index.ejs
index 6073ac7..cdac035 100644
--- a/views/index.ejs
+++ b/views/index.ejs
@@ -3,8 +3,11 @@