flink-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject [07/26] flink git commit: [FLINK-2358] [dashboard] Add first stub of angular.js based dashboard.
Date Tue, 21 Jul 2015 19:10:46 GMT
http://git-wip-us.apache.org/repos/asf/flink/blob/d59cebd8/flink-runtime-web/web-dashboard/assets/fonts/fontawesome-webfont.ttf
----------------------------------------------------------------------
diff --git a/flink-runtime-web/web-dashboard/assets/fonts/fontawesome-webfont.ttf b/flink-runtime-web/web-dashboard/assets/fonts/fontawesome-webfont.ttf
new file mode 100644
index 0000000..ed9372f
Binary files /dev/null and b/flink-runtime-web/web-dashboard/assets/fonts/fontawesome-webfont.ttf
differ

http://git-wip-us.apache.org/repos/asf/flink/blob/d59cebd8/flink-runtime-web/web-dashboard/assets/fonts/fontawesome-webfont.woff
----------------------------------------------------------------------
diff --git a/flink-runtime-web/web-dashboard/assets/fonts/fontawesome-webfont.woff b/flink-runtime-web/web-dashboard/assets/fonts/fontawesome-webfont.woff
new file mode 100644
index 0000000..8b280b9
Binary files /dev/null and b/flink-runtime-web/web-dashboard/assets/fonts/fontawesome-webfont.woff
differ

http://git-wip-us.apache.org/repos/asf/flink/blob/d59cebd8/flink-runtime-web/web-dashboard/assets/fonts/fontawesome-webfont.woff2
----------------------------------------------------------------------
diff --git a/flink-runtime-web/web-dashboard/assets/fonts/fontawesome-webfont.woff2 b/flink-runtime-web/web-dashboard/assets/fonts/fontawesome-webfont.woff2
new file mode 100644
index 0000000..3311d58
Binary files /dev/null and b/flink-runtime-web/web-dashboard/assets/fonts/fontawesome-webfont.woff2
differ

http://git-wip-us.apache.org/repos/asf/flink/blob/d59cebd8/flink-runtime-web/web-dashboard/assets/images/flink-logo.png
----------------------------------------------------------------------
diff --git a/flink-runtime-web/web-dashboard/assets/images/flink-logo.png b/flink-runtime-web/web-dashboard/assets/images/flink-logo.png
new file mode 100644
index 0000000..088fb27
Binary files /dev/null and b/flink-runtime-web/web-dashboard/assets/images/flink-logo.png
differ

http://git-wip-us.apache.org/repos/asf/flink/blob/d59cebd8/flink-runtime-web/web-dashboard/bower.json
----------------------------------------------------------------------
diff --git a/flink-runtime-web/web-dashboard/bower.json b/flink-runtime-web/web-dashboard/bower.json
new file mode 100644
index 0000000..6ecd655
--- /dev/null
+++ b/flink-runtime-web/web-dashboard/bower.json
@@ -0,0 +1,41 @@
+{
+  "name": "flink-dashboard",
+  "version": "1.0.0",
+  "authors": [
+    "Piotr Godek <piotr.godek@gmail.com>"
+  ],
+  "license": "The Apache Software Foundation Individual Contributor License Agreement",
+  "private": true,
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "test",
+    "tests"
+  ],
+  "dependencies": {
+    "bootstrap": "~3.3.5",
+    "bootstrap-less": "~3.3.4",
+    "angular": "~1.3.15",
+    "angular-ui-router": "~0.2.13",
+    "d3": "~3.5.5",
+    "dagre-d3": "~0.4.8",
+    "font-awesome": "~4.3.0",
+    "angular-moment": "~0.9.2",
+    "moment-duration-format": "~1.3.0"
+  },
+  "overrides": {
+    "dagre-d3": {
+      "main": {
+        "development": "dist/dagre-d3.core.js",
+        "production": "dist/dagre-d3.core.min.js"
+      }
+    },
+    "dagre": {
+      "main": {
+        "development": "dist/dagre.core.js",
+        "production": "dist/dagre.core.min.js"
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/flink/blob/d59cebd8/flink-runtime-web/web-dashboard/gulpfile.js
----------------------------------------------------------------------
diff --git a/flink-runtime-web/web-dashboard/gulpfile.js b/flink-runtime-web/web-dashboard/gulpfile.js
new file mode 100644
index 0000000..8bcb8a0
--- /dev/null
+++ b/flink-runtime-web/web-dashboard/gulpfile.js
@@ -0,0 +1,156 @@
+var gulp = require('gulp');
+var gutil = require('gulp-util');
+var jade = require('gulp-jade');
+var livereload = require('gulp-livereload');
+var plumber = require('gulp-plumber');
+var stylus = require('gulp-stylus');
+var browserify = require('gulp-browserify');
+var concat = require('gulp-concat');
+var uglify = require('gulp-uglify');
+var ngAnnotate = require('gulp-ng-annotate');
+var minify = require('gulp-minify-css');
+var serve = require('gulp-serve');
+var nib = require('nib');
+var coffee = require('gulp-coffee');
+var sourcemaps = require('gulp-sourcemaps');
+var filter = require('gulp-filter');
+var mainBowerFiles = require('main-bower-files');
+var less = require('gulp-less');
+var path = require('path');
+
+var environment = 'development';
+var paths = {
+  src: './app/',
+  dest: './web/',
+  vendor: './vendor/',
+  vendorLocal: './vendor-local/',
+  assets: './assets/',
+  tmp: './tmp/'
+}
+
+gulp.task('set-production', function() {
+  environment = 'production';
+});
+
+gulp.task('fonts', function() {
+ gulp.src(paths.vendor + "font-awesome/fonts/*")
+    .pipe(plumber())
+    .pipe(gulp.dest(paths.assets + 'fonts'));
+});
+
+gulp.task('assets', function() {
+ gulp.src(paths.assets + "**")
+    .pipe(plumber())
+    .pipe(gulp.dest(paths.dest));
+});
+
+
+gulp.task('bootstrap', function () {
+  return gulp.src(paths.src + 'styles/bootstrap_custom.less')
+    .pipe(less({
+      paths: [ path.join(__dirname, 'less', 'includes') ]
+    }))
+    .pipe(gulp.dest(paths.tmp + 'css/'));
+});
+
+gulp.task('vendor-styles', [ 'bootstrap' ], function() {
+  stream = gulp.src(mainBowerFiles().concat([paths.tmp + 'css/bootstrap_custom.css']))
+    .pipe(filter(['*.css', '!bootstrap.css']))
+    .pipe(sourcemaps.init())
+    .pipe(concat("vendor.css"))
+    .pipe(sourcemaps.write());
+
+  if (environment == 'production') {
+    stream.pipe(minify())
+  }
+
+  stream.pipe(gulp.dest(paths.dest + 'css/'))
+ });
+
+gulp.task('vendor-scripts', function() {
+  stream = gulp.src(mainBowerFiles({
+      env: 'development'
+    }).concat([paths.vendorLocal + '*.js']))
+    .pipe(filter('*.js'))
+    .pipe(sourcemaps.init())
+    .pipe(concat("vendor.js"))
+    .pipe(sourcemaps.write());
+
+  if (environment == 'production') {
+    stream.pipe(uglify())
+  }
+
+  stream.pipe(gulp.dest(paths.dest + 'js/'))
+ });
+
+gulp.task('scripts', function() {
+  stream = gulp.src([ paths.src + 'scripts/config.js', paths.src + 'scripts/**/*.coffee']
)
+    .pipe(plumber())
+    .pipe(sourcemaps.init())
+    .pipe(coffee({ bare: true }))
+    .pipe(ngAnnotate())
+    .pipe(concat('index.js'))
+    .pipe(sourcemaps.write());
+
+  if (environment == 'production') {
+    stream.pipe(uglify())
+  }
+
+  stream.pipe(gulp.dest(paths.dest + 'js/'))
+});
+
+gulp.task('html', function() {
+  gulp.src(paths.src + 'index.jade')
+    .pipe(plumber())
+    .pipe(jade({
+      pretty: true
+    }))
+    .pipe(gulp.dest(paths.dest))
+});
+
+gulp.task('partials', function() {
+  gulp.src(paths.src + 'partials/**/*.jade')
+    .pipe(plumber())
+    .pipe(jade({
+      pretty: true
+    }))
+    .pipe(gulp.dest(paths.dest + 'partials/'))
+});
+
+gulp.task('styles', function () {
+  stream = gulp.src(paths.src + 'styles/index.styl')
+    .pipe(plumber())
+    .pipe(stylus({ use: [nib()] }))
+  
+  if (environment == 'production') {
+    stream.pipe(minify());
+  }
+
+  stream.pipe(gulp.dest(paths.dest + 'css/'))
+});
+
+gulp.task('watch', function () {
+  livereload.listen();
+
+  gulp.watch(paths.src + 'partials/**', ['partials']);
+  gulp.watch(paths.src + 'scripts/**', ['scripts']);
+  gulp.watch(paths.src + 'styles/**/*.styl', ['styles']);
+  gulp.watch(paths.src + 'index.jade', ['html']);
+
+  gulp.watch([
+      paths.dest + 'js/*.js',
+      paths.dest + 'css/*.css',
+      paths.dest + '**/*.html'
+    ], livereload.changed);
+});
+
+gulp.task('serve', serve({
+  root: 'web',
+  port: 3001
+}));
+
+gulp.task('vendor', ['vendor-styles', 'vendor-scripts']);
+gulp.task('compile', ['html', 'partials','styles', 'scripts']);
+
+gulp.task('default', ['fonts', 'assets', 'vendor', 'compile']);
+gulp.task('production', ['set-production', 'default']);

http://git-wip-us.apache.org/repos/asf/flink/blob/d59cebd8/flink-runtime-web/web-dashboard/package.json
----------------------------------------------------------------------
diff --git a/flink-runtime-web/web-dashboard/package.json b/flink-runtime-web/web-dashboard/package.json
new file mode 100644
index 0000000..0df5602
--- /dev/null
+++ b/flink-runtime-web/web-dashboard/package.json
@@ -0,0 +1,37 @@
+{
+  "name": "flink-dashboard",
+  "version": "1.0.0",
+  "author": "Piotr Godek",
+  "description": "",
+  "repository": "",
+  "devDependencies": {
+    "browserify": "^9.0.3",
+    "coffeeify": "^1.0.0",
+    "gulp": "^3.8.11",
+    "gulp-browserify": "^0.5.1",
+    "gulp-coffee": "^2.3.1",
+    "gulp-coffeeify": "^0.1.8",
+    "gulp-concat": "^2.5.2",
+    "gulp-filter": "^2.0.2",
+    "gulp-jade": "^1.0.0",
+    "gulp-less": "^3.0.2",
+    "gulp-livereload": "^3.8.0",
+    "gulp-minify-css": "^1.0.0",
+    "gulp-ng-annotate": "^0.5.2",
+    "gulp-plumber": "^1.0.0",
+    "gulp-rename": "^1.2.0",
+    "gulp-serve": "^0.3.1",
+    "gulp-sourcemaps": "^1.5.1",
+    "gulp-stylus": "^2.0.1",
+    "gulp-uglify": "^1.1.0",
+    "gulp-util": "^3.0.4",
+    "jade": "^1.9.2",
+    "jadeify": "^4.1.0",
+    "main-bower-files": "^2.6.2",
+    "nib": "^1.1.0",
+    "path": "^0.11.14"
+  },
+  "dependencies": {
+    "hapi": "^8.4.0"
+  }
+}

http://git-wip-us.apache.org/repos/asf/flink/blob/d59cebd8/flink-runtime-web/web-dashboard/server.js
----------------------------------------------------------------------
diff --git a/flink-runtime-web/web-dashboard/server.js b/flink-runtime-web/web-dashboard/server.js
new file mode 100644
index 0000000..447aeea
--- /dev/null
+++ b/flink-runtime-web/web-dashboard/server.js
@@ -0,0 +1,45 @@
+var Hapi = require('hapi');
+
+var server = new Hapi.Server();
+var remotes = [
+  { port: 8080, path: 'web-server' },
+  { port: 8081, path: 'job-server' },
+  { port: 8082, path: 'new-server' }
+]
+
+server.connection({ port: 3000 });
+
+remotes.forEach(function (remote) {
+  server.route([
+    {
+      method: 'GET',
+      path: '/' + remote.path + '/{params*}',
+      handler: {
+        proxy: {
+          mapUri: function(request, callback) {
+            var url = "http://localhost:" + remote.port + "/" + request.url.href.replace('/'
+ remote.path + '/', '');
+            console.log(request.url.href, '->', url);
+            callback(null, url);
+          },
+          passThrough: true,
+          xforward: true
+        }
+      }
+    }
+  ]);
+});
+
+server.route({
+  method: 'GET',
+  path: '/{param*}',
+  handler: {
+    directory: {
+      path: 'web',
+      listing: true
+    }
+  }
+});
+
+server.start(function () {
+  console.log('Server running at:', server.info.uri);
+});

http://git-wip-us.apache.org/repos/asf/flink/blob/d59cebd8/flink-runtime-web/web-dashboard/vendor-local/d3-timeline.js
----------------------------------------------------------------------
diff --git a/flink-runtime-web/web-dashboard/vendor-local/d3-timeline.js b/flink-runtime-web/web-dashboard/vendor-local/d3-timeline.js
new file mode 100644
index 0000000..0c6fcdd
--- /dev/null
+++ b/flink-runtime-web/web-dashboard/vendor-local/d3-timeline.js
@@ -0,0 +1,567 @@
+// vim: ts=2 sw=2
+(function () {
+  d3.timeline = function() {
+    var DISPLAY_TYPES = ["circle", "rect"];
+
+    var hover = function () {},
+        mouseover = function () {},
+        mouseout = function () {},
+        click = function () {},
+        scroll = function () {},
+        labelFunction = function() {},
+        orient = "bottom",
+        width = null,
+        height = null,
+        rowSeperatorsColor = null,
+        backgroundColor = null,
+        tickFormat = { format: d3.time.format("%I %p"),
+          tickTime: d3.time.hours,
+          tickInterval: 1,
+          tickSize: 6 },
+        colorCycle = d3.scale.category20(),
+        colorPropertyName = null,
+        display = "rect",
+        beginning = 0,
+        ending = 0,
+        margin = {left: 30, right:30, top: 30, bottom:30},
+        stacked = false,
+        rotateTicks = false,
+        timeIsRelative = false,
+        itemHeight = 20,
+        itemMargin = 5,
+        showTimeAxis = true,
+        showTodayLine = false,
+        timeAxisTick = false,
+        timeAxisTickFormat = {stroke: "stroke-dasharray", spacing: "4 10"},
+        showTodayFormat = {marginTop: 25, marginBottom: 0, width: 1, color: colorCycle},
+        showBorderLine = false,
+        showBorderFormat = {marginTop: 25, marginBottom: 0, width: 1, color: colorCycle}
+      ;
+
+    function timeline (gParent) {
+      var g = gParent.append("g");
+      var gParentSize = gParent[0][0].getBoundingClientRect();
+
+      var gParentItem = d3.select(gParent[0][0]);
+
+      var yAxisMapping = {},
+        maxStack = 1,
+        minTime = 0,
+        maxTime = 0;
+
+      setWidth();
+
+      // check if the user wants relative time
+      // if so, substract the first timestamp from each subsequent timestamps
+      if(timeIsRelative){
+        g.each(function (d, i) {
+          d.forEach(function (datum, index) {
+            datum.times.forEach(function (time, j) {
+              if(index === 0 && j === 0){
+                originTime = time.starting_time;               //Store the timestamp that
will serve as origin
+                time.starting_time = 0;                        //Set the origin
+                time.ending_time = time.ending_time - originTime;     //Store the relative
time (millis)
+              }else{
+                time.starting_time = time.starting_time - originTime;
+                time.ending_time = time.ending_time - originTime;
+              }
+            });
+          });
+        });
+      }
+
+      // check how many stacks we're gonna need
+      // do this here so that we can draw the axis before the graph
+      if (stacked || ending === 0 || beginning === 0) {
+        g.each(function (d, i) {
+          d.forEach(function (datum, index) {
+
+            // create y mapping for stacked graph
+            if (stacked && Object.keys(yAxisMapping).indexOf(index) == -1) {
+              yAxisMapping[index] = maxStack;
+              maxStack++;
+            }
+
+            // figure out beginning and ending times if they are unspecified
+            datum.times.forEach(function (time, i) {
+              if(beginning === 0)
+                if (time.starting_time < minTime || (minTime === 0 && timeIsRelative
=== false))
+                  minTime = time.starting_time;
+              if(ending === 0)
+                if (time.ending_time > maxTime)
+                  maxTime = time.ending_time;
+            });
+          });
+        });
+
+        if (ending === 0) {
+          ending = maxTime;
+        }
+        if (beginning === 0) {
+          beginning = minTime;
+        }
+      }
+
+      var scaleFactor = (1/(ending - beginning)) * (width - margin.left - margin.right);
+
+      // draw the axis
+      var xScale = d3.time.scale()
+        .domain([beginning, ending])
+        .range([margin.left, width - margin.right]);
+
+      var xAxis = d3.svg.axis()
+        .scale(xScale)
+        .orient(orient)
+        .tickFormat(tickFormat.format)
+        .ticks(tickFormat.numTicks || tickFormat.tickTime, tickFormat.tickInterval)
+        .tickSize(tickFormat.tickSize);
+
+      if (showTimeAxis) {
+        g.append("g")
+          .attr("class", "axis")
+          .attr("transform", "translate(" + 0 +","+(margin.top + (itemHeight + itemMargin)
* maxStack)+")")
+          .call(xAxis);
+      }
+
+      if (timeAxisTick) {
+        g.append("g")
+          .attr("class", "axis")
+          .attr("transform", "translate(" + 0 +","+
+            (margin.top + (itemHeight + itemMargin) * maxStack)+")")
+          .attr(timeAxisTickFormat.stroke, timeAxisTickFormat.spacing)
+          .call(xAxis.tickFormat("").tickSize(-(margin.top + (itemHeight + itemMargin) *
(maxStack - 1) + 3),0,0));
+      }
+      
+      // draw the chart
+      g.each(function(d, i) {
+        d.forEach( function(datum, index){
+          var data = datum.times;
+          var hasLabel = (typeof(datum.label) != "undefined");
+          var getLabel = function(label){
+            if(labelFunction == null){
+              return label;
+            } else {
+              return labelFunction(label);
+            }
+          };
+
+          // issue warning about using id per data set. Ids should be individual to data
elements
+          if (typeof(datum.id) != "undefined") {
+            console.warn("d3Timeline Warning: Ids per dataset is deprecated in favor of a
'class' key. Ids are now per data element.");
+          }
+
+          if (backgroundColor) {
+            var greenbarYAxis = ((itemHeight + itemMargin) * yAxisMapping[index]);
+            g.selectAll("svg").data(data).enter()
+              .insert("rect")
+              .attr("class", "row-green-bar")
+              .attr("x", 0 + margin.left)
+              .attr("width", width - margin.right - margin.left)
+              .attr("y", greenbarYAxis)
+              .attr("height", itemHeight)
+              .attr("fill", backgroundColor)
+            ;
+          }
+
+          g.selectAll("svg").data(data).enter()
+            .append(function(d, i) {
+                return document.createElementNS(d3.ns.prefix.svg, "display" in d? d.display:display);
+            })
+            .attr("x", getXPos)
+            .attr("y", getStackPosition)
+            .attr("width", function (d, i) {
+              return (d.ending_time - d.starting_time) * scaleFactor;
+            })
+            .attr("cy", function(d, i) {
+                return getStackPosition(d, i) + itemHeight/2;
+            })
+            .attr("cx", getXPos)
+            .attr("r", itemHeight / 2)
+            .attr("height", itemHeight)
+            // .style("fill", function(d, i) {
+            //   return "#ffffff";
+            // })
+            .style("fill", function(d, i){
+              var dColorPropName;
+              if (d.color) return d.color;
+              if( colorPropertyName ){
+                dColorPropName = d[colorPropertyName];
+                if ( dColorPropName ) {
+                  return colorCycle( dColorPropName );
+                } else {
+                  return colorCycle( datum[colorPropertyName] );
+                }
+              }
+              return colorCycle(index);
+            })
+            .on("mousemove", function (d, i) {
+              hover(d, index, datum);
+            })
+            .on("mouseover", function (d, i) {
+              mouseover(d, i, datum);
+            })
+            .on("mouseout", function (d, i) {
+              mouseout(d, i, datum);
+            })
+            .on("click", function (d, i) {
+              click(d, index, datum);
+            })
+            .attr("class", function (d, i) {
+              return datum.class ? "timeline-series timelineSeries_"+datum.class : "timeline-series
timelineSeries_"+index;
+            })
+            .attr("id", function(d, i) {
+              // use deprecated id field
+              if (datum.id && !d.id) {
+                return 'timelineItem_'+datum.id;
+              }
+              
+              return d.id ? d.id : "timelineItem_"+index+"_"+i;
+            })
+          ;
+
+          g.selectAll("svg").data(data).enter()
+            .append("text")
+            .attr("class", "timeline-insidelabel")
+            .attr("x", getXTextPos)
+            .attr("y", getStackTextPosition)
+            .attr("width", function (d, i) {
+              // console.log((d.ending_time - d.starting_time) * scaleFactor);
+              return (d.ending_time - d.starting_time) * scaleFactor;
+            })
+            .text(function(d) {
+              return d.label;
+            })
+            .on("click", function (d, i) {
+              click(d, index, datum);
+            });
+          ;
+
+          if (rowSeperatorsColor) {
+            var lineYAxis = ( itemHeight + itemMargin / 2 + margin.top + (itemHeight + itemMargin)
* yAxisMapping[index]);
+            gParent.append("svg:line")
+              .attr("class", "row-seperator")
+              .attr("x1", 0 + margin.left)
+              .attr("x2", width - margin.right)
+              .attr("y1", lineYAxis)
+              .attr("y2", lineYAxis)
+              .attr("stroke-width", 1)
+              .attr("stroke", rowSeperatorsColor);
+            ;
+          }
+
+          // add the label
+          if (hasLabel) {
+            gParent.append("text")
+              .attr("class", "timeline-label")
+              .attr("transform", "translate("+ 0 +","+ (itemHeight * 0.75 + margin.top +
(itemHeight + itemMargin) * yAxisMapping[index])+")")
+              .text(hasLabel ? getLabel(datum.label) : datum.id)
+              .on("click", function (d, i) {
+                click(d, index, datum);
+              });
+          }
+
+          if (typeof(datum.icon) !== "undefined") {
+            gParent.append("image")
+              .attr("class", "timeline-label")
+              .attr("transform", "translate("+ 0 +","+ (margin.top + (itemHeight + itemMargin)
* yAxisMapping[index])+")")
+              .attr("xlink:href", datum.icon)
+              .attr("width", margin.left)
+              .attr("height", itemHeight);
+          }
+
+          function getStackPosition(d, i) {
+            if (stacked) {
+              return margin.top + (itemHeight + itemMargin) * yAxisMapping[index];
+            }
+            return margin.top;
+          }
+          function getStackTextPosition(d, i) {
+            if (stacked) {
+              return margin.top + (itemHeight + itemMargin) * yAxisMapping[index] + itemHeight
* 0.75;
+            }
+            return margin.top + itemHeight * 0.75;
+          }
+        });
+      });
+
+      if (width > gParentSize.width) {
+        var move = function() {
+          var x = Math.min(0, Math.max(gParentSize.width - width, d3.event.translate[0]));
+          zoom.translate([x, 0]);
+          g.attr("transform", "translate(" + x + ",0)");
+          scroll(x*scaleFactor, xScale);
+        };
+
+        var zoom = d3.behavior.zoom().x(xScale).on("zoom", move);
+
+        gParent
+          .attr("class", "scrollable")
+          .call(zoom);
+      }
+
+      if (rotateTicks) {
+        g.selectAll(".tick text")
+          .attr("transform", function(d) {
+            return "rotate(" + rotateTicks + ")translate("
+              + (this.getBBox().width / 2 + 10) + "," // TODO: change this 10
+              + this.getBBox().height / 2 + ")";
+          });
+      }
+
+      var gSize = g[0][0].getBoundingClientRect();
+      setHeight();
+
+      if (showBorderLine) {
+        g.each(function (d, i) {
+          d.forEach(function (datum) {
+            var times = datum.times;
+            times.forEach(function (time) {
+              appendLine(xScale(time.starting_time), showBorderFormat);
+              appendLine(xScale(time.ending_time), showBorderFormat);
+            });
+          });
+        });
+      }
+
+      if (showTodayLine) {
+        var todayLine = xScale(new Date());
+        appendLine(todayLine, showTodayFormat);
+      }
+
+      function getXPos(d, i) {
+        return margin.left + (d.starting_time - beginning) * scaleFactor;
+      }
+
+      function getXTextPos(d, i) {
+        return margin.left + (d.starting_time - beginning) * scaleFactor + 5;
+      }
+
+      function setHeight() {
+        if (!height && !gParentItem.attr("height")) {
+          if (itemHeight) {
+            // set height based off of item height
+            height = gSize.height + gSize.top - gParentSize.top;
+            // set bounding rectangle height
+            d3.select(gParent[0][0]).attr("height", height);
+          } else {
+            throw "height of the timeline is not set";
+          }
+        } else {
+          if (!height) {
+            height = gParentItem.attr("height");
+          } else {
+            gParentItem.attr("height", height);
+          }
+        }
+      }
+
+      function setWidth() {
+        if (!width && !gParentSize.width) {
+          try { 
+            width = gParentItem.attr("width");
+            if (!width) {
+              throw "width of the timeline is not set. As of Firefox 27, timeline().with(x)
needs to be explicitly set in order to render";
+            }            
+          } catch (err) {
+            console.log( err );
+          }
+        } else if (!(width && gParentSize.width)) {
+          try { 
+            width = gParentItem.attr("width");
+          } catch (err) {
+            console.log( err );
+          }
+        }
+        // if both are set, do nothing
+      }
+
+      function appendLine(lineScale, lineFormat) {
+        gParent.append("svg:line")
+          .attr("x1", lineScale)
+          .attr("y1", lineFormat.marginTop)
+          .attr("x2", lineScale)
+          .attr("y2", height - lineFormat.marginBottom)
+          .style("stroke", lineFormat.color)//"rgb(6,120,155)")
+          .style("stroke-width", lineFormat.width);
+      }
+
+    }
+
+    // SETTINGS
+
+    timeline.margin = function (p) {
+      if (!arguments.length) return margin;
+      margin = p;
+      return timeline;
+    };
+
+    timeline.orient = function (orientation) {
+      if (!arguments.length) return orient;
+      orient = orientation;
+      return timeline;
+    };
+
+    timeline.itemHeight = function (h) {
+      if (!arguments.length) return itemHeight;
+      itemHeight = h;
+      return timeline;
+    };
+
+    timeline.itemMargin = function (h) {
+      if (!arguments.length) return itemMargin;
+      itemMargin = h;
+      return timeline;
+    };
+
+    timeline.height = function (h) {
+      if (!arguments.length) return height;
+      height = h;
+      return timeline;
+    };
+
+    timeline.width = function (w) {
+      if (!arguments.length) return width;
+      width = w;
+      return timeline;
+    };
+
+    timeline.display = function (displayType) {
+      if (!arguments.length || (DISPLAY_TYPES.indexOf(displayType) == -1)) return display;
+      display = displayType;
+      return timeline;
+    };
+
+    timeline.labelFormat = function(f) {
+      if (!arguments.length) return null;
+      labelFunction = f;
+      return timeline;
+    };
+
+    timeline.tickFormat = function (format) {
+      if (!arguments.length) return tickFormat;
+      tickFormat = format;
+      return timeline;
+    };
+
+    timeline.hover = function (hoverFunc) {
+      if (!arguments.length) return hover;
+      hover = hoverFunc;
+      return timeline;
+    };
+
+    timeline.mouseover = function (mouseoverFunc) {
+      if (!arguments.length) return mouseoverFunc;
+      mouseover = mouseoverFunc;
+      return timeline;
+    };
+
+    timeline.mouseout = function (mouseoverFunc) {
+      if (!arguments.length) return mouseoverFunc;
+      mouseout = mouseoverFunc;
+      return timeline;
+    };
+
+    timeline.click = function (clickFunc) {
+      if (!arguments.length) return click;
+      click = clickFunc;
+      return timeline;
+    };
+
+    timeline.scroll = function (scrollFunc) {
+      if (!arguments.length) return scroll;
+      scroll = scrollFunc;
+      return timeline;
+    };
+
+    timeline.colors = function (colorFormat) {
+      if (!arguments.length) return colorCycle;
+      colorCycle = colorFormat;
+      return timeline;
+    };
+
+    timeline.beginning = function (b) {
+      if (!arguments.length) return beginning;
+      beginning = b;
+      return timeline;
+    };
+
+    timeline.ending = function (e) {
+      if (!arguments.length) return ending;
+      ending = e;
+      return timeline;
+    };
+
+    timeline.rotateTicks = function (degrees) {
+      rotateTicks = degrees;
+      return timeline;
+    };
+
+    timeline.stack = function () {
+      stacked = !stacked;
+      return timeline;
+    };
+
+    timeline.relativeTime = function() {
+      timeIsRelative = !timeIsRelative;
+      return timeline;
+    };
+
+    timeline.showBorderLine = function () {
+        showBorderLine = !showBorderLine;
+        return timeline;
+    };
+
+    timeline.showBorderFormat = function(borderFormat) {
+      if (!arguments.length) return showBorderFormat;
+      showBorderFormat = borderFormat;
+      return timeline;
+    };
+
+    timeline.showToday = function () {
+      showTodayLine = !showTodayLine;
+      return timeline;
+    };
+
+    timeline.showTodayFormat = function(todayFormat) {
+      if (!arguments.length) return showTodayFormat;
+      showTodayFormat = todayFormat;
+      return timeline;
+    };
+
+    timeline.colorProperty = function(colorProp) {
+      if (!arguments.length) return colorPropertyName;
+      colorPropertyName = colorProp;
+      return timeline;
+    };
+
+    timeline.rowSeperators = function (color) {
+      if (!arguments.length) return rowSeperatorsColor;
+      rowSeperatorsColor = color;
+      return timeline;
+    };
+
+    timeline.background = function (color) {
+      if (!arguments.length) return backgroundColor;
+      backgroundColor = color;
+      return timeline;
+    };
+
+    timeline.showTimeAxis = function () {
+      showTimeAxis = !showTimeAxis;
+      return timeline;
+    };
+
+    timeline.showTimeAxisTick = function () {
+      timeAxisTick = !timeAxisTick;
+      return timeline;
+    };
+
+    timeline.showTimeAxisTickFormat = function(format) {
+      if (!arguments.length) return timeAxisTickFormat;
+      timeAxisTickFormat = format;
+      return timeline;
+    }
+
+    return timeline;
+  };
+})();

http://git-wip-us.apache.org/repos/asf/flink/blob/d59cebd8/flink-runtime-web/web-dashboard/web/css/index.css
----------------------------------------------------------------------
diff --git a/flink-runtime-web/web-dashboard/web/css/index.css b/flink-runtime-web/web-dashboard/web/css/index.css
new file mode 100644
index 0000000..dd6c91e
--- /dev/null
+++ b/flink-runtime-web/web-dashboard/web/css/index.css
@@ -0,0 +1,410 @@
+#sidebar {
+  overflow: hidden;
+  position: fixed;
+  left: -250px;
+  top: 0;
+  bottom: 0;
+  height: 100%;
+  width: 250px;
+  background: #151515;
+  -webkit-transition: 400ms;
+  -moz-transition: 400ms;
+  -o-transition: 400ms;
+  -ms-transition: 400ms;
+  transition: 400ms;
+  -webkit-box-shadow: inset -10px 0px 10px rgba(0,0,0,0.2);
+  box-shadow: inset -10px 0px 10px rgba(0,0,0,0.2);
+}
+#sidebar.sidebar-visible {
+  left: 0;
+}
+#sidebar .logo {
+  width: auto;
+  height: 22px;
+}
+#sidebar .navbar-brand.navbar-brand-text {
+  font-size: 14px;
+  font-weight: bold;
+  color: #fff;
+  padding-left: 0;
+}
+#sidebar .nav > li > a {
+  color: #aaa;
+  margin-bottom: 1px;
+}
+#sidebar .nav > li > a:hover,
+#sidebar .nav > li > a:focus {
+  background-color: rgba(40,40,40,0.5);
+}
+#sidebar .nav > li > a.active {
+  background-color: rgba(100,100,100,0.5);
+}
+#content {
+  background-color: #fff;
+  overflow: hidden;
+  margin-left: 0;
+  padding-top: 70px;
+  -webkit-transition: 400ms;
+  -moz-transition: 400ms;
+  -o-transition: 400ms;
+  -ms-transition: 400ms;
+  transition: 400ms;
+}
+#content .navbar-main,
+#content .navbar-main-additional {
+  -webkit-transition: 400ms;
+  -moz-transition: 400ms;
+  -o-transition: 400ms;
+  -ms-transition: 400ms;
+  transition: 400ms;
+}
+#content .navbar-main-additional {
+  margin-top: 51px;
+  border-bottom: none;
+  padding: 0 20px;
+}
+#content .navbar-main-additional .nav-tabs {
+  margin: 0 -20px;
+  padding: 0 20px;
+}
+#content.sidebar-visible {
+  margin-left: 250px;
+}
+#content.sidebar-visible .navbar-main,
+#content.sidebar-visible .navbar-main-additional {
+  left: 250px;
+}
+#content #fold-button {
+  display: inline-block;
+  margin-left: 20px;
+}
+#content #content-inner {
+  padding: 0px 20px 20px 20px;
+}
+#content #content-inner.has-navbar-main-additional {
+  padding-top: 42px;
+}
+.page-header {
+  margin: 0 0 20px 0;
+}
+.nav > li > a,
+.nav > li > a:hover,
+.nav > li > a:focus {
+  color: #aaa;
+  background-color: transparent;
+  border-bottom: 2px solid transparent;
+}
+.nav > li.active > a,
+.nav > li.active > a:hover,
+.nav > li.active > a:focus {
+  color: #000;
+  border-bottom: 2px solid #000;
+}
+.nav.nav-tabs {
+  margin-bottom: 20px;
+}
+.table th {
+  font-weight: normal;
+  color: #999;
+}
+.table.table-clickable tr {
+  cursor: pointer;
+}
+.panel.panel-dashboard .huge {
+  font-size: 28px;
+}
+.panel.panel-lg {
+  font-size: 16px;
+}
+.panel.panel-lg .badge {
+  font-size: 14px;
+}
+.navbar-secondary {
+  overflow: auto;
+}
+.navbar-main .navbar-title,
+.navbar-secondary .navbar-title,
+.navbar-main-additional .navbar-title,
+.panel.panel-multi .navbar-title,
+.navbar-main .panel-title,
+.navbar-secondary .panel-title,
+.navbar-main-additional .panel-title,
+.panel.panel-multi .panel-title {
+  float: left;
+  font-size: 18px;
+  padding: 12px 20px 13px 10px;
+  color: #333;
+  display: inline-block;
+}
+.navbar-main .navbar-info,
+.navbar-secondary .navbar-info,
+.navbar-main-additional .navbar-info,
+.panel.panel-multi .navbar-info,
+.navbar-main .panel-info,
+.navbar-secondary .panel-info,
+.navbar-main-additional .panel-info,
+.panel.panel-multi .panel-info {
+  float: left;
+  font-size: 14px;
+  padding: 15px 15px 15px 15px;
+  color: #999;
+  display: inline-block;
+  border-right: 1px solid #e7e7e7;
+  overflow: hidden;
+}
+.navbar-main .navbar-info .overflow,
+.navbar-secondary .navbar-info .overflow,
+.navbar-main-additional .navbar-info .overflow,
+.panel.panel-multi .navbar-info .overflow,
+.navbar-main .panel-info .overflow,
+.navbar-secondary .panel-info .overflow,
+.navbar-main-additional .panel-info .overflow,
+.panel.panel-multi .panel-info .overflow {
+  position: absolute;
+  display: block;
+  -o-text-overflow: ellipsis;
+  text-overflow: ellipsis;
+  overflow: hidden;
+  height: 22px;
+  line-height: 22px;
+  vertical-align: middle;
+}
+.navbar-main .navbar-info.first,
+.navbar-secondary .navbar-info.first,
+.navbar-main-additional .navbar-info.first,
+.panel.panel-multi .navbar-info.first,
+.navbar-main .panel-info.first,
+.navbar-secondary .panel-info.first,
+.navbar-main-additional .panel-info.first,
+.panel.panel-multi .panel-info.first {
+  border-left: 1px solid #e7e7e7;
+}
+.navbar-main .navbar-info.last,
+.navbar-secondary .navbar-info.last,
+.navbar-main-additional .navbar-info.last,
+.panel.panel-multi .navbar-info.last,
+.navbar-main .panel-info.last,
+.navbar-secondary .panel-info.last,
+.navbar-main-additional .panel-info.last,
+.panel.panel-multi .panel-info.last {
+  border-right: none;
+}
+.panel.panel-multi .panel-heading {
+  padding: 0;
+}
+.panel.panel-multi .panel-body {
+  padding: 10px;
+  background-color: #fdfdfd;
+  color: #999;
+  font-size: 13px;
+}
+.navbar-main-additional {
+  min-height: 40px;
+  background-color: #fdfdfd;
+}
+.navbar-main-additional .navbar-info {
+  font-size: 13px;
+  padding: 10px 15px 10px 15px;
+}
+.nav-top-affix.affix {
+  width: 100%;
+  top: 50px;
+  margin-left: -20px;
+  padding-left: 20px;
+  margin-right: -20px;
+  padding-right: 20px;
+  background-color: #fff;
+  z-index: 1;
+}
+.badge-default[href]:hover,
+.badge-default[href]:focus {
+  background-color: #808080;
+}
+.badge-primary {
+  background-color: #428bca;
+}
+.badge-primary[href]:hover,
+.badge-primary[href]:focus {
+  background-color: #3071a9;
+}
+.badge-success {
+  background-color: #5cb85c;
+}
+.badge-success[href]:hover,
+.badge-success[href]:focus {
+  background-color: #449d44;
+}
+.badge-info {
+  background-color: #5bc0de;
+}
+.badge-info[href]:hover,
+.badge-info[href]:focus {
+  background-color: #31b0d5;
+}
+.badge-warning {
+  background-color: #f0ad4e;
+}
+.badge-warning[href]:hover,
+.badge-warning[href]:focus {
+  background-color: #ec971f;
+}
+.badge-danger {
+  background-color: #d9534f;
+}
+.badge-danger[href]:hover,
+.badge-danger[href]:focus {
+  background-color: #c9302c;
+}
+.indicator {
+  display: inline-block;
+  margin-right: 15px;
+}
+.indicator.indicator-primary {
+  color: #428bca;
+}
+.indicator.indicator-success {
+  color: #5cb85c;
+}
+.indicator.indicator-info {
+  color: #5bc0de;
+}
+.indicator.indicator-warning {
+  color: #f0ad4e;
+}
+.indicator.indicator-danger {
+  color: #d9534f;
+}
+.canvas-wrapper {
+  border: 1px solid #ddd;
+  position: relative;
+  margin-bottom: 20px;
+}
+.canvas-wrapper .main-canvas {
+  height: 400px;
+  overflow: hidden;
+}
+.canvas-wrapper .main-canvas .zoom-buttons {
+  position: absolute;
+  top: 10px;
+  right: 10px;
+}
+.table.table-properties {
+  table-layout: fixed;
+  white-space: nowrap;
+}
+.table.table-properties td {
+  width: 50%;
+  white-space: nowrap;
+  overflow: hidden;
+  -o-text-overflow: ellipsis;
+  text-overflow: ellipsis;
+}
+.label-group .label {
+  display: inline-block;
+  width: 2em;
+  padding-left: 0.1em;
+  padding-right: 0.1em;
+  margin: 0;
+  border-right: 1px solid #fff;
+  -webkit-border-radius: 0;
+  border-radius: 0;
+}
+.label-group .label.label-black {
+  background-color: #000;
+}
+svg.graph {
+  overflow: hidden;
+}
+svg.graph g.type-TK > rect {
+  fill: #00ffd0;
+}
+svg.graph text {
+  font-weight: 300;
+  font-size: 14px;
+}
+svg.graph .node > rect {
+  stroke: #999;
+  stroke-width: 5px;
+  fill: #fff;
+  margin: 0;
+}
+svg.graph .node[active] > rect {
+  fill: #eee;
+}
+svg.graph .node.node-mirror > rect {
+  stroke: #a8a8a8;
+}
+svg.graph .node.node-iteration > rect {
+  stroke: #cd3333;
+}
+svg.graph .node.node-source > rect {
+  stroke: #4ce199;
+}
+svg.graph .node.node-sink > rect {
+  stroke: #e6ec8b;
+}
+svg.graph .node.node-normal > rect {
+  stroke: #3fb6d8;
+}
+svg.graph .node h4 {
+  color: #000;
+}
+svg.graph .node h5 {
+  color: #999;
+}
+svg.graph .edgeLabel rect {
+  fill: #fff;
+}
+svg.graph .edgePath path {
+  stroke: #333;
+  stroke-width: 2px;
+  fill: #333;
+}
+svg.graph .label {
+  color: #777;
+  margin: 0;
+}
+svg.graph .edge-label {
+  padding: 5px;
+  font-size: 14px;
+}
+svg.graph .node-label {
+  display: block;
+  margin: 0;
+  text-decoration: none;
+}
+.timeline-canvas {
+  overflow: hidden;
+  padding: 10px;
+}
+svg.timeline {
+  overflow: hidden;
+}
+svg.timeline .timeline-insidelabel,
+svg.timeline .timeline-series {
+  cursor: pointer;
+}
+svg.timeline.secondary .timeline-insidelabel,
+svg.timeline.secondary .timeline-series {
+  cursor: auto;
+}
+@media (min-width: 768px) {
+  #sidebar {
+    left: 0;
+  }
+  #content {
+    margin-left: 250px;
+  }
+  #content #fold-button {
+    display: none;
+  }
+  #content .navbar-main,
+  #content .navbar-main-additional {
+    left: 250px;
+  }
+  .navbar-main .navbar-title,
+  .navbar-secondary .navbar-title,
+  .navbar-main-additional .navbar-title {
+    padding: 12px 20px 13px 20px;
+  }
+}


Mime
View raw message