azkaban-aplcache

Details

diff --git a/azkaban-web-server/build.gradle b/azkaban-web-server/build.gradle
index 182fdd9..b242e4d 100644
--- a/azkaban-web-server/build.gradle
+++ b/azkaban-web-server/build.gradle
@@ -11,8 +11,32 @@ buildscript {
   }
 }
 
+// This node plugin enables users to run any NodeJS script.  The plugin will download and 
+// manage NodeJS distributions, use them from there.
+// ***npm install*** installs all dependencies in package.json. It will only run when changes are made to package.json
 plugins {
-    id 'com.craigburke.bower-installer' version '2.5.1'
+  id "com.moowork.node" version "0.13"
+}
+
+node {
+  // Version of node to use.
+  version = '6.2.1'
+
+  // Version of npm to use.
+  npmVersion = '3.9.3'
+
+  // Base URL for fetching node distributions (change if you have a mirror).
+  distBaseUrl = 'https://nodejs.org/dist'
+
+  // If true, it will download node using above parameters.
+  // If false, it will try to use globally installed node.
+  download = true
+
+  // Set the work directory for unpacking node
+  workDir = file("${project.buildDir}/nodejs")
+
+  // Set the work directory where node_modules should be located
+  nodeModulesDir = file("${project.projectDir}")
 }
 
 apply plugin: 'lesscss'
@@ -50,27 +74,44 @@ sourceSets {
   }
 }
 
-bower {
-  installBase = 'bower' // <1>
+task movingJsTojsToPackage(dependsOn: ['npm_install']) {
 
-  'moment'('2.14.1'){
-    source 'min/moment.min.js' >> '/'
+  doLast {
+    copy {
+      from "node_modules/later/later.min.js"
+      into "${buildDir}/jsToPackage"
+    }
+    copy {
+      from "node_modules/moment/min/moment.min.js"
+      into "${buildDir}/jsToPackage"
+    }
+    copy {
+      from "node_modules/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js"
+      into "${buildDir}/jsToPackage"
+    }
+    copy {
+      from "node_modules/moment-timezone/builds/moment-timezone-with-data-2010-2020.min.js"
+      into "${buildDir}/jsToPackage"
+    }
   }
+}
 
-  'moment-timezone'('0.5.5') {
-    source 'builds/moment-timezone-with-data-2010-2020.min.js'  >> '/'
-  }
+task cleanAll {
+  delete 'jsToPackage'
+  delete 'node_modules'
+  delete 'velocity.log'
+}
+clean.dependsOn cleanAll
 
-  'eonasdan-bootstrap-datetimepicker'('4.0.0') {
-    source 'build/js/*.min.js'  >> '/'
-    excludes 'jquery'
-  }
+task jsTest(dependsOn: ['npm_install'], type: NodeTask) {
 
-  'later'('1.2.0'){
-    source 'later.min.js' >> '/'
-  }
+  // refer to mocha js script file.
+  script = file('node_modules/mocha/bin/mocha')
+
+  // args keep the test files' location
+  args = ['src/web/js/azkaban/test/']
 }
-clean.dependsOn 'bowerClean'
+test.dependsOn jsTest
 
 task restliTemplateGenerator(type: JavaExec) {
   mkdir 'src/restli/generatedJava'
@@ -133,10 +174,10 @@ distributions {
       from (dustjs) {
         into 'web/js'
       }
-      from ('bower') {
+      from ('build/jsToPackage') {
         into 'web/js'
       }
-      from (bowerInstall) {
+      from (movingJsTojsToPackage) {
         into 'web/js'
       }
     }
diff --git a/azkaban-web-server/package.json b/azkaban-web-server/package.json
new file mode 100644
index 0000000..b6bdfcb
--- /dev/null
+++ b/azkaban-web-server/package.json
@@ -0,0 +1,25 @@
+{
+  "_comment": "This json is called by npm install",
+  "name": "azkaban",
+  "description": "Azkaban 3 [![Build Status](http://img.shields.io/travis/azkaban/azkaban.svg?style=flat)](https://travis-ci.org/azkaban/azkaban) ========",
+  "dependencies": {
+    "mocha": "^3.0.2",
+    "rewire": "^2.5.2",
+    "chai": "^3.5.0",
+    "later": "^1.2.0",
+    "eonasdan-bootstrap-datetimepicker": "^4.0.0",
+    "moment-timezone": "^0.5.5",
+    "moment": "^2.14.1"
+  },
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/azkaban/azkaban.git"
+  },
+  "bugs": {
+    "url": "https://github.com/azkaban/azkaban/issues"
+  },
+  "homepage": "https://azkaban.github.io/"
+}
diff --git a/azkaban-web-server/src/web/js/azkaban/test/test.js b/azkaban-web-server/src/web/js/azkaban/test/test.js
new file mode 100644
index 0000000..eb1f95b
--- /dev/null
+++ b/azkaban-web-server/src/web/js/azkaban/test/test.js
@@ -0,0 +1,52 @@
+function addClass(el, newClass) {
+ if(el.className.indexOf(newClass) === -1) {
+   el.className += newClass;
+ }
+}
+
+var rewire = require('rewire'),
+    dateJs = rewire('../util/date.js');
+
+var chai = require('chai');
+var assert = chai.assert;
+
+//Some Test instances
+describe('addClass', function() {
+ it('should add class into element', function() {
+   var element = { className: '' };
+
+   addClass(element, 'test-class');
+
+   assert.equal(element.className, 'test-class');
+ });
+
+ it('should not add a class which already exists in element', function() {
+   var element = { className: 'exists' };
+
+   addClass(element, 'exists');
+
+   var numClasses = element.className.split(' ').length;
+   assert.equal(numClasses, 1);
+ });
+
+ // it('should append new class after existing one', function() {
+ //    var element = { className: 'exists' };
+ //    addClass(element, 'new-class');
+ //    var classes = element.className.split(' ');
+ //    assert.equal(classes[1], 'new-class');
+ //  });
+});
+
+
+//Test the functionality from Unix Cron to Quartz
+describe('CronTransformation', function() {
+
+  var testStrFromCronToQuartz = dateJs.__get__('transformFromQuartzToUnixCron');
+
+  it('should transfer correctly', function() {
+
+   assert.equal(testStrFromCronToQuartz('0 3 * * 5'), '0 3 * * 4');
+   assert.equal(testStrFromCronToQuartz('0 3 * * 5-7'), '0 3 * * 4-6');
+   assert.equal(testStrFromCronToQuartz('0 3 * * 1,3-5 2016'), '0 3 * * 0,2-4 2016');
+  });
+});
diff --git a/azkaban-web-server/src/web/js/azkaban/util/date.js b/azkaban-web-server/src/web/js/azkaban/util/date.js
index abe9fad..0243286 100644
--- a/azkaban-web-server/src/web/js/azkaban/util/date.js
+++ b/azkaban-web-server/src/web/js/azkaban/util/date.js
@@ -94,7 +94,7 @@ var getTwoDigitStr = function(value) {
   return value;
 }
 
-function modifyStrToUnixCronSyntax(str){
+var modifyStrToUnixCronSyntax = function (str){
   return str.replace(/[0-7]/g, function upperToHyphenLower(match) {
     return (parseInt(match)+6)%7;
   });
@@ -103,7 +103,7 @@ function modifyStrToUnixCronSyntax(str){
 // Unix Cron use 0-6 as Sun--Sat, but Quartz use 1-7. Due to later.js only supporting Unix Cron, we have to make this transition.
 // The detailed Unix Cron Syntax: https://en.wikipedia.org/wiki/Cron
 // The input is a 5 field string (without year) or 6 field String (with year).
-function transformFromQuartzToUnixCron(str){
+var transformFromQuartzToUnixCron = function (str){
   var res = str.split(" ");
 
   // If the cron doesn't include year field