<commit_before>
module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        build: {
            path: 'build/<%= pkg.version %>',
            vendor: '<%= build.path %>/vendor'
        },
        clean: {
            dist: ['<%= build.path %>/*']
        },
        jshint: {
            files: ['Gruntfile.js', 'src/**/*.js'],
            options: {
                globals: {
                    jQuery: true
                }
            }
        },
        concat: {
            options: {
                sourceMap: true
            },
            vendors: {
                src: [
                    './bower_components/webcomponentsjs/webcomponents-lite.js',
                    './bower_components/jquery/dist/jquery.js',
                    './bower_components/underscore/underscore.js',
                    './bower_components/backbone/backbone.js',
                    './bower_components/highcharts-release/highcharts.js',
                    './bower_components/qtip2/jquery.qtip.js',
                    './bower_components/uri.js/src/URI.js',
                    './bower_components/cookies-js/dist/cookies.js',
                    './bower_components/moment/moment.js',
                    './bower_components/crypto-js/crypto-js.js'
                ],
                dest: '<%= build.path %>/vendors.js'
            },
            jsorolla: {
                src: [
                    './lib/jsorolla/src/lib/clients/rest-client.js',
                    './lib/jsorolla/src/lib/clients/cellbase-client-config.js',
                    './lib//jsorolla/src/lib/clients/cellbase-client.js',
                    './lib/jsorolla/src/lib/clients/opencga-client-config.js',
                    './lib/jsorolla/src/lib/clients/opencga-client.js',
                    './lib/jsorolla/src/lib/cache/indexeddb-cache.js',
                    './lib/jsorolla/src/lib/utils.js',
                    './lib/jsorolla/src/lib/svg.js',
                    './lib/jsorolla/src/lib/visualisation/lollipop.js'
                ],
                dest: '<%= build.path %>/jsorolla-clients.js'
            },
            genomeViewer: {
                src: [
                    './lib/jsorolla/build/2.0.0-beta/genome-viewer/gv-config.js',
                    './lib/jsorolla/build/2.0.0-beta/genome-viewer/genome-viewer.js'
                ],
                dest: '<%= build.path %>/genome-viewer.js'
            }
        },
        uglify: {
            options: {
                banner: '/*! IVA <%= grunt.template.today("dd-mm-yyyy") %> */\n'
            },
            dist: {
                files: {
                    '<%= build.path %>/vendors.min.js': ['<%= build.path %>/vendors.js'],
                    // '<%= build.path %>/jsorolla.min.js': ['<%= build.path %>/jsorolla-clients.js']
                }
            }
        },
        copy: {
            dist: {
                files: [
                    {   flatten: true, expand: true, cwd: './bower_components', src: ['fontawesome/css/font-awesome.min.css'], dest: '<%= build.path %>/css' },
                    {   flatten: true, expand: true, cwd: './bower_components', src: ['qtip2/jquery.qtip.min.css'], dest: '<%= build.path %>/css' },
                    {   flatten: true, expand: true, cwd: './bower_components', src: ['fontawesome/fonts/*'], dest: '<%= build.path %>/fonts' },
                    {   flatten: true, expand: true, cwd: './lib', src: ['jsorolla/styles/css/style.css'], dest: '<%= build.path %>/css' },
                    {   expand: true, cwd: './bower_components', src: ['polymer/*'], dest: '<%= build.vendor %>' },
                    {   expand: true, cwd: 'src', src: ['index.html'], dest: '<%= build.path %>/' },
                    {   expand: true, cwd: 'src', src: ['config.js'], dest: '<%= build.path %>/' },
                    {   expand: true, cwd: './', src: ['LICENSE'], dest: '<%= build.path %>/' },
                    {   expand: true, cwd: 'src', src: ['images/*'], dest: '<%= build.path %>/' }
                ]
            }
        },
        processhtml: {
            options: {
                strip: true
            },
            dist: {
                files: {
                    '<%= build.path %>/index.html': ['src/index.html']
                }
            }
        },
        vulcanize: {
            default: {
                options: {
                    // Task-specific options go here.
                    stripComments: true,
                    excludes: ["bower_components/polymer/polymer.html"]
                },
                files: {
                    '<%= build.path %>/iva-app.html': 'src/iva-app.html'
                }
            }
        },
        watch: {
            files: ['<%= jshint.files %>'],
            tasks: ['jshint']
        },
        replace: {
            dist: {
                options: {
                    patterns: [
                        {
                            match: /\.\.\/bower_components/g,
                            replacement: 'vendor'
                        }
                    ]
                },
                files: [
                    {expand: true, flatten: true, src: ['<%= build.path %>/index.html'], dest: '<%= build.path %>'},
                    {expand: true, flatten: true, src: ['<%= build.path %>/iva-app.html'], dest: '<%= build.path %>'},

                ]
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-processhtml');
    grunt.loadNpmTasks('grunt-vulcanize');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-replace');

    grunt.registerTask('default', ['clean', 'jshint', 'copy', 'concat', 'uglify', 'processhtml', 'vulcanize', 'replace']);
    grunt.registerTask('cl', ['clean']);
};<commit_msg>Replace single quotes with double<commit_after>
module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON("package.json"),
        build: {
            path: "build/<%= pkg.version %>",
            vendor: "<%= build.path %>/vendor"
        },
        clean: {
            dist: ["<%= build.path %>/*"]
        },
        jshint: {
            files: ["Gruntfile.js", "src/**/*.js"],
            options: {
                globals: {
                    jQuery: true
                }
            }
        },
        concat: {
            options: {
                sourceMap: true
            },
            vendors: {
                src: [
                    "./bower_components/webcomponentsjs/webcomponents-lite.js",
                    "./bower_components/jquery/dist/jquery.js",
                    "./bower_components/underscore/underscore.js",
                    "./bower_components/backbone/backbone.js",
                    "./bower_components/highcharts-release/highcharts.js",
                    "./bower_components/qtip2/jquery.qtip.js",
                    "./bower_components/uri.js/src/URI.js",
                    "./bower_components/cookies-js/dist/cookies.js",
                    "./bower_components/moment/moment.js",
                    "./bower_components/crypto-js/crypto-js.js"
                ],
                dest: "<%= build.path %>/vendors.js"
            },
            jsorolla: {
                src: [
                    "./lib/jsorolla/src/lib/clients/rest-client.js",
                    "./lib/jsorolla/src/lib/clients/cellbase-client-config.js",
                    "./lib//jsorolla/src/lib/clients/cellbase-client.js",
                    "./lib/jsorolla/src/lib/clients/opencga-client-config.js",
                    "./lib/jsorolla/src/lib/clients/opencga-client.js",
                    "./lib/jsorolla/src/lib/cache/indexeddb-cache.js",
                    "./lib/jsorolla/src/lib/utils.js",
                    "./lib/jsorolla/src/lib/svg.js",
                    "./lib/jsorolla/src/lib/visualisation/lollipop.js"
                ],
                dest: "<%= build.path %>/jsorolla-clients.js"
            },
            genomeViewer: {
                src: [
                    "./lib/jsorolla/build/2.0.0-beta/genome-viewer/gv-config.js",
                    "./lib/jsorolla/build/2.0.0-beta/genome-viewer/genome-viewer.js"
                ],
                dest: "<%= build.path %>/genome-viewer.js"
            }
        },
        uglify: {
            options: {
                banner: "/*! IVA <%= grunt.template.today(\"dd-mm-yyyy\") %> */\n"
            },
            dist: {
                files: {
                    "<%= build.path %>/vendors.min.js": ["<%= build.path %>/vendors.js"],
                    // '<%= build.path %>/jsorolla.min.js': ['<%= build.path %>/jsorolla-clients.js']
                }
            }
        },
        copy: {
            dist: {
                files: [
                    {   flatten: true, expand: true, cwd: "./bower_components", src: ["fontawesome/css/font-awesome.min.css"], dest: "<%= build.path %>/css" },
                    {   flatten: true, expand: true, cwd: "./bower_components", src: ["qtip2/jquery.qtip.min.css"], dest: "<%= build.path %>/css" },
                    {   flatten: true, expand: true, cwd: "./bower_components", src: ["fontawesome/fonts/*"], dest: "<%= build.path %>/fonts" },
                    {   flatten: true, expand: true, cwd: "./lib", src: ["jsorolla/styles/css/style.css"], dest: "<%= build.path %>/css" },
                    {   expand: true, cwd: "./bower_components", src: ["polymer/*"], dest: "<%= build.vendor %>" },
                    {   expand: true, cwd: "src", src: ["index.html"], dest: "<%= build.path %>/" },
                    {   expand: true, cwd: "src", src: ["config.js"], dest: "<%= build.path %>/" },
                    {   expand: true, cwd: "./", src: ["LICENSE"], dest: "<%= build.path %>/" },
                    {   expand: true, cwd: "src", src: ["images/*"], dest: "<%= build.path %>/" }
                ]
            }
        },
        processhtml: {
            options: {
                strip: true
            },
            dist: {
                files: {
                    "<%= build.path %>/index.html": ["src/index.html"]
                }
            }
        },
        vulcanize: {
            default: {
                options: {
                    // Task-specific options go here.
                    stripComments: true,
                    excludes: ["bower_components/polymer/polymer.html"]
                },
                files: {
                    "<%= build.path %>/iva-app.html": "src/iva-app.html"
                }
            }
        },
        watch: {
            files: ["<%= jshint.files %>"],
            tasks: ["jshint"]
        },
        replace: {
            dist: {
                options: {
                    patterns: [
                        {
                            match: /\.\.\/bower_components/g,
                            replacement: "vendor"
                        }
                    ]
                },
                files: [
                    {expand: true, flatten: true, src: ["<%= build.path %>/index.html"], dest: "<%= build.path %>"},
                    {expand: true, flatten: true, src: ["<%= build.path %>/iva-app.html"], dest: "<%= build.path %>"},

                ]
            }
        }
    });

    grunt.loadNpmTasks("grunt-contrib-clean");
    grunt.loadNpmTasks("grunt-contrib-jshint");
    grunt.loadNpmTasks("grunt-contrib-copy");
    grunt.loadNpmTasks("grunt-contrib-concat");
    grunt.loadNpmTasks("grunt-contrib-uglify");
    grunt.loadNpmTasks("grunt-processhtml");
    grunt.loadNpmTasks("grunt-vulcanize");
    grunt.loadNpmTasks("grunt-contrib-watch");
    grunt.loadNpmTasks("grunt-replace");

    grunt.registerTask("default", ["clean", "jshint", "copy", "concat", "uglify", "processhtml", "vulcanize", "replace"]);
    grunt.registerTask("cl", ["clean"]);
};<|endoftext|>


<commit_before>import styled, { css } from 'styled-components';
import { StyledFormFooter } from '../../__deprecated__/components/form/form.style.js';
import { StyledEditAction } from '../pod/pod.style.js';
import Pod from '../pod';
import Link from '../link';
import { isClassic } from '../../utils/helpers/style-helper';
import StyledDeleteButton from './delete-button.style.js';
import { baseTheme } from '../../style/themes';

const StyledPod = styled(Pod)`
  ${StyledFormFooter} {
    margin-top: ${({ theme }) => (isClassic(theme) ? 20 : 24)}px;
  }

  ${StyledEditAction} {
    ${({ theme }) => !isClassic(theme) && css`
      > a, button {
        height: 16px;
        width: 16px;
        padding: 20px;
      }
    `};
  }

  ${StyledDeleteButton} {
    color: ${({ theme }) => theme.colors.error};

    &:hover {
      color: ${({ theme }) => theme.colors.destructive.hover};
    }
  }

  .common-input__prefix {
    z-index: 5;
  }

  .carbon-show-edit-pod__transition-enter {
    opacity: 0;
  }

  .carbon-show-edit-pod__transition-enter.carbon-show-edit-pod__transition-enter-active {
    opacity: 1;
    transition: all 300ms ease-in;
  }

  .carbon-show-edit-pod__transition-exit {
    opacity: 0;
    position: absolute;
  }
`;

StyledPod.defaultProps = {
  theme: baseTheme
};

const StyledLink = styled(Link)`
  a {
    color: #C7384F;

    &:hover {
      color: #C11E20;
    }
  }
`;

export { StyledPod, StyledLink };
<commit_msg>style(show-edit-pod): change edit button padding<commit_after>import styled, { css } from 'styled-components';
import { StyledFormFooter } from '../../__deprecated__/components/form/form.style.js';
import { StyledEditAction } from '../pod/pod.style.js';
import Pod from '../pod';
import Link from '../link';
import { isClassic } from '../../utils/helpers/style-helper';
import StyledDeleteButton from './delete-button.style.js';
import { baseTheme } from '../../style/themes';

const StyledPod = styled(Pod)`
  ${StyledFormFooter} {
    margin-top: ${({ theme }) => (isClassic(theme) ? 20 : 24)}px;
  }

  ${StyledEditAction} {
    ${({ theme }) => !isClassic(theme) && css`
      > a, button {
        height: 16px;
        width: 16px;
        padding: 16px;
      }
    `};
  }

  ${StyledDeleteButton} {
    color: ${({ theme }) => theme.colors.error};

    &:hover {
      color: ${({ theme }) => theme.colors.destructive.hover};
    }
  }

  .common-input__prefix {
    z-index: 5;
  }

  .carbon-show-edit-pod__transition-enter {
    opacity: 0;
  }

  .carbon-show-edit-pod__transition-enter.carbon-show-edit-pod__transition-enter-active {
    opacity: 1;
    transition: all 300ms ease-in;
  }

  .carbon-show-edit-pod__transition-exit {
    opacity: 0;
    position: absolute;
  }
`;

StyledPod.defaultProps = {
  theme: baseTheme
};

const StyledLink = styled(Link)`
  a {
    color: #C7384F;

    &:hover {
      color: #C11E20;
    }
  }
`;

export { StyledPod, StyledLink };
<|endoftext|>


<commit_before>$.get('http://repairnator.lille.inria.fr/repairnator-mongo-api/scanners/weeksData/2', function (dataScanner) {
  console.log(data);
  var htmlElement = $('

');
  $('#charts').append(htmlElement);

  /*
   {
   '_id': '58e22490cefc9665e4354cde',
   'hostname': 'repairnator',
   'dateBegin': '2017-04-03T12:00:00.000Z',
   'dateLimit': '2017-04-03T08:00:00.000Z',
   'dayLimit': '03/04/2017',
   'totalRepoNumber': 1611,
   'totalRepoUsingTravis': 1601,
   'totalScannedBuilds': 205,
   'totalJavaBuilds': 198,
   'totalJavaPassingBuilds': 152,
   'totalJavaFailingBuilds': 27,
   'totalJavaFailingBuildsWithFailingTests': 8,
   'totalPRBuilds': 52,
   'duration': '0:31:4',
   'runId': '92d87100-e392-4b7c-8f49-2789af76ef7c',
   'dateBeginStr': '03/04/17 12:00',
   'dateLimitStr': '03/04/17 08:00'
   },
   */

  var reducedData = dataScanner.reduce(function (accumulator, currentValue) {
    if (accumulator.length == 0) {
      return [ currentValue ];
    } else {
      var previousValue = accumulator[accumulator.length - 1];

      if (previousValue.dayLimit === currentValue.dayLimit) {
        for (var attr in previousValue) {
          if (attr.indexOf('total') != -1 && attr.indexOf('totalRepoNumber') == -1) {
            previousValue[attr] += currentValue[attr];
          }
        }
      } else {
        accumulator.push(currentValue);
      }

      return accumulator;
    }
  }, []);

  $.get('http://repairnator.lille.inria.fr/repairnator-mongo-api/inspector/reproducedBuilds/14', function (dataInspector) {
    Highcharts.chart({
      chart: {
        type: 'spline',
        renderTo: htmlElement[0]
      },
      title: {
        text: 'Number of scanned and reproduced builds on the last 2 weeks'
      },
      xAxis: {
        type: 'datetime',
        dateTimeLabelFormats: { // don't display the dummy year
          day:'%A, %b %e',
        },
        title: {
          text: 'Date'
        }
      },
      yAxis: {
        title: {
          text: 'Number of builds'
        },
        min: 0
      },
      tooltip: {
        headerFormat: '{series.name}
',
        pointFormat: '{point.x:%A, %b %e}: {point.y} builds'
      },

      plotOptions: {
        spline: {
          marker: {
            enabled: true
          }
        }
      },

      series: [
        {
          name: 'Builds to reproduce',
          data: reducedData.map( function (d) {
            return [
              Date.parse(d.dateLimit),
              d.totalJavaFailingBuildsWithFailingTests
            ]
          })
        },
        {
          name: 'Builds succeed to reproduce',
          data: dataInspector.map( function (d) {
            return [
              moment(d._id, 'YYYY-MM-DD').toDate(),
              d.counted
            ]
          })
        }
      ]
    });
  });
});

$.get('http://repairnator.lille.inria.fr/repairnator-mongo-api/scanners/', function (data) {
  var htmlElement = $('

');
  $('#charts').append(htmlElement);

  var currentWeek = moment().week();

  var reducedData = data.reduce(function (accumulator, currentValue) {
    var currentValueWeek = moment(currentValue.dateLimit).week();

    if (accumulator.length == 0) {
      if (currentValueWeek === currentWeek) {
        return [];
      } else {
        return [ currentValue ];
      }
    } else {
      var previousValue = accumulator[accumulator.length - 1];
      var previousValueWeek = moment(previousValue.dateLimit).week();

      if (currentValueWeek === currentWeek) {
        return accumulator;
      }
      if (previousValueWeek === currentValueWeek) {
        for (var attr in previousValue) {
          if (attr.indexOf('total') != -1 && attr.indexOf('totalRepoNumber') == -1) {
            previousValue[attr] += currentValue[attr];
          }
        }
      } else {
        accumulator.push(currentValue);
      }

      return accumulator;
    }
  }, []);

  /*
   {
   '_id': '58e22490cefc9665e4354cde',
   'hostname': 'repairnator',
   'dateBegin': '2017-04-03T12:00:00.000Z',
   'dateLimit': '2017-04-03T08:00:00.000Z',
   'dayLimit': '03/04/2017',
   'totalRepoNumber': 1611,
   'totalRepoUsingTravis': 1601,
   'totalScannedBuilds': 205,
   'totalJavaBuilds': 198,
   'totalJavaPassingBuilds': 152,
   'totalJavaFailingBuilds': 27,
   'totalJavaFailingBuildsWithFailingTests': 8,
   'totalPRBuilds': 52,
   'duration': '0:31:4',
   'runId': '92d87100-e392-4b7c-8f49-2789af76ef7c',
   'dateBeginStr': '03/04/17 12:00',
   'dateLimitStr': '03/04/17 08:00'
   },
   */

  (function (H) {
    // Pass error messages
    H.Axis.prototype.allowNegativeLog = true;

    // Override conversions
    H.Axis.prototype.log2lin = function (num) {
      var isNegative = num < 0,
        adjustedNum = Math.abs(num),
        result;
      if (adjustedNum < 10) {
        adjustedNum += (10 - adjustedNum) / 10;
      }
      result = Math.log(adjustedNum) / Math.LN10;
      return isNegative ? -result : result;
    };
    H.Axis.prototype.lin2log = function (num) {
      var isNegative = num < 0,
        absNum = Math.abs(num),
        result = Math.pow(10, absNum);
      if (result < 10) {
        result = (10 * (result - 1)) / (10 - 1);
      }
      return isNegative ? -result : result;
    };
  }(Highcharts));

  Highcharts.chart({
    chart: {
      type: 'spline',
      renderTo: htmlElement[0],
      width: undefined,
      height: 700
    },
    exporting: {
      enabled: true,
      sourceWidth: 1200,
      sourceHeight: 600
    },
    title: {
      text: 'Number of scanned projects and builds per week'
    },
    xAxis: {
      type: 'datetime',
      dateTimeLabelFormats: { // don't display the dummy year
        week:'%e %b %Y',
      },
      title: {
        text: 'Date'
      }
    },
    yAxis: {
      type: 'logarithmic',
      minorTickInterval: 1,
      title: {
        text: 'Number of builds or projects'
      },
      min: 20
    },
    tooltip: {
      headerFormat: '{series.name}
',
      pointFormat: '{point.x:%A, %b %e}: {point.y} builds'
    },

    plotOptions: {
      spline: {
        marker: {
          enabled: true
        },
        dataLabels: {
          enabled: false
        },
      },
    },

    series: [
      {
        name: 'Scanned repositories',
        data: reducedData.map( function (d) {
          return [
            Date.parse(d.dateLimit),
            d.totalRepoNumber
          ]
        })
      },
      {
        name: 'Scanned builds',
        data: reducedData.map( function (d) {
          return [
            Date.parse(d.dateLimit),
            d.totalScannedBuilds
          ]
        })
      },
      {
        name: 'Scanned Java builds',
        data: reducedData.map( function (d) {
          return [
            Date.parse(d.dateLimit),
            d.totalJavaBuilds
          ]
        })
      },
      {
        name: 'Scanned Java failing builds',
        data: reducedData.map( function (d) {
          return [
            Date.parse(d.dateLimit),
            d.totalJavaFailingBuilds
          ]
        })
      },
      {
        name: 'Scanned Java failing builds with failing tests',
        data: reducedData.map( function (d) {
          return [
            Date.parse(d.dateLimit),
            d.totalJavaFailingBuildsWithFailingTests
          ]
        })
      }
    ]
  });
});
<commit_msg>Fix website for displaying reproduced builds values<commit_after>$.get('http://repairnator.lille.inria.fr/repairnator-mongo-api/scanners/weeksData/2', function (dataScanner) {
  var htmlElement = $('

');
  $('#charts').append(htmlElement);

  /*
   {
   '_id': '58e22490cefc9665e4354cde',
   'hostname': 'repairnator',
   'dateBegin': '2017-04-03T12:00:00.000Z',
   'dateLimit': '2017-04-03T08:00:00.000Z',
   'dayLimit': '03/04/2017',
   'totalRepoNumber': 1611,
   'totalRepoUsingTravis': 1601,
   'totalScannedBuilds': 205,
   'totalJavaBuilds': 198,
   'totalJavaPassingBuilds': 152,
   'totalJavaFailingBuilds': 27,
   'totalJavaFailingBuildsWithFailingTests': 8,
   'totalPRBuilds': 52,
   'duration': '0:31:4',
   'runId': '92d87100-e392-4b7c-8f49-2789af76ef7c',
   'dateBeginStr': '03/04/17 12:00',
   'dateLimitStr': '03/04/17 08:00'
   },
   */

  var reducedData = dataScanner.reduce(function (accumulator, currentValue) {
    if (accumulator.length == 0) {
      return [ currentValue ];
    } else {
      var previousValue = accumulator[accumulator.length - 1];

      if (previousValue.dayLimit === currentValue.dayLimit) {
        for (var attr in previousValue) {
          if (attr.indexOf('total') != -1 && attr.indexOf('totalRepoNumber') == -1) {
            previousValue[attr] += currentValue[attr];
          }
        }
      } else {
        accumulator.push(currentValue);
      }

      return accumulator;
    }
  }, []);

  $.get('http://repairnator.lille.inria.fr/repairnator-mongo-api/inspectors/reproducedBuilds/14', function (dataInspector) {
    Highcharts.chart({
      chart: {
        type: 'spline',
        renderTo: htmlElement[0]
      },
      title: {
        text: 'Number of scanned and reproduced builds on the last 2 weeks'
      },
      xAxis: {
        type: 'datetime',
        dateTimeLabelFormats: { // don't display the dummy year
          day:'%A, %b %e',
        },
        title: {
          text: 'Date'
        }
      },
      yAxis: {
        title: {
          text: 'Number of builds'
        },
        min: 0
      },
      tooltip: {
        headerFormat: '{series.name}
',
        pointFormat: '{point.x:%A, %b %e}: {point.y} builds'
      },

      plotOptions: {
        spline: {
          marker: {
            enabled: true
          },
          dataLabels: {
            enabled: true
          },
        },
      },

      series: [
        {
          name: 'Builds to reproduce',
          data: reducedData.map( function (d) {
            return [
              Date.parse(d.dateLimit),
              d.totalJavaFailingBuildsWithFailingTests
            ]
          })
        },
        {
          name: 'Builds succeed to reproduce',
          data: dataInspector.map( function (d) {
            return [
              moment(d._id, 'YYYY-MM-DD').valueOf(),
              d.counted
            ]
          })
        }
      ]
    });
  });
});

$.get('http://repairnator.lille.inria.fr/repairnator-mongo-api/scanners/', function (data) {
  var htmlElement = $('

');
  $('#charts').append(htmlElement);

  var currentWeek = moment().week();

  var reducedData = data.reduce(function (accumulator, currentValue) {
    var currentValueWeek = moment(currentValue.dateLimit).week();

    if (accumulator.length == 0) {
      if (currentValueWeek === currentWeek) {
        return [];
      } else {
        return [ currentValue ];
      }
    } else {
      var previousValue = accumulator[accumulator.length - 1];
      var previousValueWeek = moment(previousValue.dateLimit).week();

      if (currentValueWeek === currentWeek) {
        return accumulator;
      }
      if (previousValueWeek === currentValueWeek) {
        for (var attr in previousValue) {
          if (attr.indexOf('total') != -1 && attr.indexOf('totalRepoNumber') == -1) {
            previousValue[attr] += currentValue[attr];
          }
        }
      } else {
        accumulator.push(currentValue);
      }

      return accumulator;
    }
  }, []);

  /*
   {
   '_id': '58e22490cefc9665e4354cde',
   'hostname': 'repairnator',
   'dateBegin': '2017-04-03T12:00:00.000Z',
   'dateLimit': '2017-04-03T08:00:00.000Z',
   'dayLimit': '03/04/2017',
   'totalRepoNumber': 1611,
   'totalRepoUsingTravis': 1601,
   'totalScannedBuilds': 205,
   'totalJavaBuilds': 198,
   'totalJavaPassingBuilds': 152,
   'totalJavaFailingBuilds': 27,
   'totalJavaFailingBuildsWithFailingTests': 8,
   'totalPRBuilds': 52,
   'duration': '0:31:4',
   'runId': '92d87100-e392-4b7c-8f49-2789af76ef7c',
   'dateBeginStr': '03/04/17 12:00',
   'dateLimitStr': '03/04/17 08:00'
   },
   */

  (function (H) {
    // Pass error messages
    H.Axis.prototype.allowNegativeLog = true;

    // Override conversions
    H.Axis.prototype.log2lin = function (num) {
      var isNegative = num < 0,
        adjustedNum = Math.abs(num),
        result;
      if (adjustedNum < 10) {
        adjustedNum += (10 - adjustedNum) / 10;
      }
      result = Math.log(adjustedNum) / Math.LN10;
      return isNegative ? -result : result;
    };
    H.Axis.prototype.lin2log = function (num) {
      var isNegative = num < 0,
        absNum = Math.abs(num),
        result = Math.pow(10, absNum);
      if (result < 10) {
        result = (10 * (result - 1)) / (10 - 1);
      }
      return isNegative ? -result : result;
    };
  }(Highcharts));

  Highcharts.chart({
    chart: {
      type: 'spline',
      renderTo: htmlElement[0],
      width: undefined,
      height: 700
    },
    exporting: {
      enabled: true,
      sourceWidth: 1200,
      sourceHeight: 600
    },
    title: {
      text: 'Number of scanned projects and builds per week'
    },
    xAxis: {
      type: 'datetime',
      dateTimeLabelFormats: { // don't display the dummy year
        week:'%e %b %Y',
      },
      title: {
        text: 'Date'
      }
    },
    yAxis: {
      type: 'logarithmic',
      minorTickInterval: 1,
      title: {
        text: 'Number of builds or projects'
      },
      min: 20
    },
    tooltip: {
      headerFormat: '{series.name}
',
      pointFormat: '{point.x:%A, %b %e}: {point.y} builds'
    },

    plotOptions: {
      spline: {
        marker: {
          enabled: true
        },
        dataLabels: {
          enabled: false
        },
      },
    },

    series: [
      {
        name: 'Scanned repositories',
        data: reducedData.map( function (d) {
          return [
            Date.parse(d.dateLimit),
            d.totalRepoNumber
          ]
        })
      },
      {
        name: 'Scanned builds',
        data: reducedData.map( function (d) {
          return [
            Date.parse(d.dateLimit),
            d.totalScannedBuilds
          ]
        })
      },
      {
        name: 'Scanned Java builds',
        data: reducedData.map( function (d) {
          return [
            Date.parse(d.dateLimit),
            d.totalJavaBuilds
          ]
        })
      },
      {
        name: 'Scanned Java failing builds',
        data: reducedData.map( function (d) {
          return [
            Date.parse(d.dateLimit),
            d.totalJavaFailingBuilds
          ]
        })
      },
      {
        name: 'Scanned Java failing builds with failing tests',
        data: reducedData.map( function (d) {
          return [
            Date.parse(d.dateLimit),
            d.totalJavaFailingBuildsWithFailingTests
          ]
        })
      }
    ]
  });
});
<|endoftext|>


<commit_before>(function($) {

/**
 * @class Echo.StreamServer.Controls.Stream.Plugins.ItemAccumulatorDisplay
 * Shows one of the item accumulators in the top right corner of each item in the Echo Stream control.
 *     new Echo.StreamServer.Controls.Stream({
 *         "target": document.getElementById("echo-stream"),
 *         "appkey": "test.echoenabled.com",
 *         "plugins": [{
 *             "name": "ItemAccumulatorDisplay"
 *         }]
 *     });
 * @extends Echo.Plugin
 * @inheritdoc Echo.Plugin
 */
var plugin = Echo.Plugin.manifest("ItemAccumulatorDisplay", "Echo.StreamServer.Controls.Stream.Item");

if (Echo.Plugin.isDefined(plugin)) return;

plugin.config = {
/**
 * @cfg {Number} countTickTimeout Specifies the timeout in seconds for sequential changes of the item accumulator during the update.
 *     new Echo.StreamServer.Controls.Stream({
 *         "target": document.getElementById("echo-stream"),
 *         "appkey": "test.echoenabled.com",
 *         "plugins": [{
 *             "name": "ItemAccumulatorDisplay"
 *             "countTickTimeout": 1,
 *             "accumulator": "likesCount"
 *         }]
 *     });
 */
	"countTickTimeout": 1,
/**
 * @cfg {String} accumulator Specifies which item accumulator should be displayed. Supported values are "repliesCount" and "likesCount".
 */
	"accumulator": "repliesCount"
};

plugin.init = function() {
	this.extendTemplate("insertBefore", "modeSwitch", plugin.template);
};

plugin.template = '

';

plugin.renderers.accumulatorContainer = function(element) {
	var item = this.component;
	var accName = this.config.get("accumulator");
	var accumulator = item.get("data.object.accumulators")[accName];
	var count = this.get("count") || {};
	if (typeof count.current === "undefined") {
		// first-time rendering actions
		this.set("count", {
			"actual": accumulator,
			"current": accumulator
		});
		return element.append(accumulator);
	}
	this._stopTimer();
	var container = item.dom.get("container");
	container.stop(true, true);
	if (count.actual !== accumulator) {
		count.actual = accumulator;
		this.set("count", count);
	}
	element.append(count.current);

	// animate counter if necessary
	if (count.current !== count.actual) {
		var bgColor = this.get("originalBGColor");
		if (typeof bgColor === "undefined") {
			bgColor = Echo.Utils.getVisibleColor(container);
			this.set("originalBGColor", bgColor);
		}
		container.css({"backgroundColor": item.config.get("parent.flashColor")});
		this._animateCounter(bgColor);
	}
	return element;
};

plugin.methods._stopTimer = function() {
	var timer = this.get("timer");
	if (timer) clearTimeout(timer);
	this.set("timer", undefined);
};

plugin.methods._animateCounter = function(bgColor) {
	this._stopTimer();
	var plugin = this;
	var count = this.get("count");
	var item = this.component;
	if (typeof count.current !== "undefined" && count.current === count.actual &&
			!this.get("animationInProgress")) {
		// fading out
		var container = item.dom.get("container");
		this.set("animationInProgress", true);
		container.animate(
			{"backgroundColor": bgColor},
			item.config.get("parent.fadeTimeout"),
			"linear",
			function() {
				container.css("backgroundColor", "");
				plugin.set("animationInProgress", false);
			}
		);
		return;
	}
	this.set("timer", setTimeout(function() {
		var count = plugin.get("count");
		if (count.current !== count.actual) {
			count.current < count.actual ? count.current++ : count.current--;
			plugin.set("count.current", count.current);
			item.dom.get("accumulatorContainer").html(count.current);
			plugin._animateCounter(bgColor);
		}
	}, this.config.get("countTickTimeout") * 1000));
};

plugin.css = '.{plugin.class:accumulatorContainer} { float: right; margin-right: 7px; }';

Echo.Plugin.create(plugin);

})(jQuery);
<commit_msg>using correct dom<commit_after>(function($) {

/**
 * @class Echo.StreamServer.Controls.Stream.Plugins.ItemAccumulatorDisplay
 * Shows one of the item accumulators in the top right corner of each item in the Echo Stream control.
 *     new Echo.StreamServer.Controls.Stream({
 *         "target": document.getElementById("echo-stream"),
 *         "appkey": "test.echoenabled.com",
 *         "plugins": [{
 *             "name": "ItemAccumulatorDisplay"
 *         }]
 *     });
 * @extends Echo.Plugin
 * @inheritdoc Echo.Plugin
 */
var plugin = Echo.Plugin.manifest("ItemAccumulatorDisplay", "Echo.StreamServer.Controls.Stream.Item");

if (Echo.Plugin.isDefined(plugin)) return;

plugin.config = {
/**
 * @cfg {Number} countTickTimeout Specifies the timeout in seconds for sequential changes of the item accumulator during the update.
 *     new Echo.StreamServer.Controls.Stream({
 *         "target": document.getElementById("echo-stream"),
 *         "appkey": "test.echoenabled.com",
 *         "plugins": [{
 *             "name": "ItemAccumulatorDisplay"
 *             "countTickTimeout": 1,
 *             "accumulator": "likesCount"
 *         }]
 *     });
 */
	"countTickTimeout": 1,
/**
 * @cfg {String} accumulator Specifies which item accumulator should be displayed. Supported values are "repliesCount" and "likesCount".
 */
	"accumulator": "repliesCount"
};

plugin.init = function() {
	this.extendTemplate("insertBefore", "modeSwitch", plugin.template);
};

plugin.template = '

';

plugin.renderers.accumulatorContainer = function(element) {
	var item = this.component;
	var accName = this.config.get("accumulator");
	var accumulator = item.get("data.object.accumulators")[accName];
	var count = this.get("count") || {};
	if (typeof count.current === "undefined") {
		// first-time rendering actions
		this.set("count", {
			"actual": accumulator,
			"current": accumulator
		});
		return element.append(accumulator);
	}
	this._stopTimer();
	var container = item.dom.get("container");
	container.stop(true, true);
	if (count.actual !== accumulator) {
		count.actual = accumulator;
		this.set("count", count);
	}
	element.append(count.current);

	// animate counter if necessary
	if (count.current !== count.actual) {
		var bgColor = this.get("originalBGColor");
		if (typeof bgColor === "undefined") {
			bgColor = Echo.Utils.getVisibleColor(container);
			this.set("originalBGColor", bgColor);
		}
		container.css({"backgroundColor": item.config.get("parent.flashColor")});
		this._animateCounter(bgColor);
	}
	return element;
};

plugin.methods._stopTimer = function() {
	var timer = this.get("timer");
	if (timer) clearTimeout(timer);
	this.set("timer", undefined);
};

plugin.methods._animateCounter = function(bgColor) {
	this._stopTimer();
	var plugin = this;
	var count = this.get("count");
	var item = this.component;
	if (typeof count.current !== "undefined" && count.current === count.actual &&
			!this.get("animationInProgress")) {
		// fading out
		var container = item.dom.get("container");
		this.set("animationInProgress", true);
		container.animate(
			{"backgroundColor": bgColor},
			item.config.get("parent.fadeTimeout"),
			"linear",
			function() {
				container.css("backgroundColor", "");
				plugin.set("animationInProgress", false);
			}
		);
		return;
	}
	this.set("timer", setTimeout(function() {
		var count = plugin.get("count");
		if (count.current !== count.actual) {
			count.current < count.actual ? count.current++ : count.current--;
			plugin.set("count.current", count.current);
			plugin.dom.get("accumulatorContainer").html(count.current);
			plugin._animateCounter(bgColor);
		}
	}, this.config.get("countTickTimeout") * 1000));
};

plugin.css = '.{plugin.class:accumulatorContainer} { float: right; margin-right: 7px; }';

Echo.Plugin.create(plugin);

})(jQuery);
<|endoftext|>


<commit_before>/*
 * Backpack - Skyscanner's Design System
 *
 * Copyright 2017 Skyscanner Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import {
  horizontalNavLinkColor,
  horizontalNavLinkHoverColor,
  horizontalNavLinkActiveColor,
  calendarDayHoverColor,
  calendarDayActiveColor,
} from 'bpk-tokens/tokens/base.es6';

const theme = {
  primaryColor300: '#865f9e',
  primaryColor500: '#461962',
  primaryColor600: '#2d244c',
  primaryColor700: '#1a1331',
  secondaryColor300: '#feee8b',
  secondaryColor500: '#fce134',
  secondaryColor600: '#f8c42d',
  secondaryColor700: '#d99916',
  white: '#fff',
};

const bpkCustomTheme = {
  accordionActiveColor: theme.primaryColor700,
  accordionColor: theme.primaryColor500,
  accordionHoverColor: theme.primaryColor600,

  barchartBarBackgroundColor: theme.primaryColor300,
  barchartBarHoverBackgroundColor: theme.primaryColor500,
  barchartBarActiveBackgroundColor: theme.primaryColor600,
  barchartBarSelectedBackgroundColor: theme.primaryColor700,

  blockquoteBarColor: theme.primaryColor500,

  buttonPrimaryTextColor: theme.primaryColor600,
  buttonPrimaryHoverTextColor: theme.primaryColor600,
  buttonPrimaryActiveTextColor: theme.primaryColor600,
  buttonPrimaryGradientStartColor: theme.secondaryColor500,
  buttonPrimaryGradientEndColor: theme.secondaryColor600,
  buttonPrimaryBackgroundColor: theme.secondaryColor600,
  buttonPrimaryHoverBackgroundColor: theme.secondaryColor600,
  buttonPrimaryActiveBackgroundColor: theme.secondaryColor700,

  buttonSecondaryTextColor: theme.primaryColor500,
  buttonSecondaryHoverTextColor: theme.primaryColor600,
  buttonSecondaryActiveTextColor: theme.primaryColor700,
  buttonSecondaryBorderColor: theme.primaryColor500,
  buttonSecondaryHoverBorderColor: theme.primaryColor600,
  buttonSecondaryActiveBorderColor: theme.primaryColor700,
  buttonSecondaryBackgroundColor: theme.white,
  buttonSecondaryHoverBackgroundColor: theme.white,
  buttonSecondaryActiveBackgroundColor: theme.white,

  linkColor: theme.primaryColor300,
  linkHoverColor: theme.primaryColor500,
  linkActiveColor: theme.primaryColor600,
  linkVisitedColor: theme.primaryColor700,

  horizontalNavBarSelectedColor: theme.primaryColor500,
  horizontalNavLinkSelectedColor: theme.primaryColor500,
  horizontalNavLinkColor,
  horizontalNavLinkHoverColor,
  horizontalNavLinkActiveColor,

  spinnerPrimaryColor: theme.primaryColor500,

  progressBarFillColor: theme.primaryColor500,

  calendarDateTextColor: theme.primaryColor500,
  calendarDateTextHoverColor: calendarDayHoverColor,
  calendarDateTextActiveColor: calendarDayActiveColor,
  calendarDateTextFocusColor: theme.primaryColor500,
  calendarDateTextSelectedColor: theme.white,
  calendarDateSelectedBackgroundColor: theme.primaryColor700,
  calendarDateFocusedBorderColor: theme.primaryColor500,
  calendarNudgerIconColor: theme.primaryColor500,
  calendarNudgerIconHoverColor: theme.primaryColor600,
  calendarNudgerIconActiveColor: theme.primaryColor700,

  checkboxCheckedColor: theme.primaryColor700,
  radioCheckedColor: theme.primaryColor700,
};

export default bpkCustomTheme;
<commit_msg>[BPK-1139]: Trying out new primary colors for theme<commit_after>/*
 * Backpack - Skyscanner's Design System
 *
 * Copyright 2017 Skyscanner Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import {
  horizontalNavLinkColor,
  horizontalNavLinkHoverColor,
  horizontalNavLinkActiveColor,
  calendarDayHoverColor,
  calendarDayActiveColor,
} from 'bpk-tokens/tokens/base.es6';

const theme = {
  primaryColor300: '#E57373',
  primaryColor500: '#F44336',
  primaryColor600: '#E53935',
  primaryColor700: '#D32F2F',
  secondaryColor300: '#feee8b',
  secondaryColor500: '#fce134',
  secondaryColor600: '#f8c42d',
  secondaryColor700: '#d99916',
  white: '#fff',
};

const bpkCustomTheme = {
  accordionActiveColor: theme.primaryColor700,
  accordionColor: theme.primaryColor500,
  accordionHoverColor: theme.primaryColor600,

  barchartBarBackgroundColor: theme.primaryColor300,
  barchartBarHoverBackgroundColor: theme.primaryColor500,
  barchartBarActiveBackgroundColor: theme.primaryColor600,
  barchartBarSelectedBackgroundColor: theme.primaryColor700,

  blockquoteBarColor: theme.primaryColor500,

  buttonPrimaryTextColor: theme.primaryColor600,
  buttonPrimaryHoverTextColor: theme.primaryColor600,
  buttonPrimaryActiveTextColor: theme.primaryColor600,
  buttonPrimaryGradientStartColor: theme.secondaryColor500,
  buttonPrimaryGradientEndColor: theme.secondaryColor600,
  buttonPrimaryBackgroundColor: theme.secondaryColor600,
  buttonPrimaryHoverBackgroundColor: theme.secondaryColor600,
  buttonPrimaryActiveBackgroundColor: theme.secondaryColor700,

  buttonSecondaryTextColor: theme.primaryColor500,
  buttonSecondaryHoverTextColor: theme.primaryColor600,
  buttonSecondaryActiveTextColor: theme.primaryColor700,
  buttonSecondaryBorderColor: theme.primaryColor500,
  buttonSecondaryHoverBorderColor: theme.primaryColor600,
  buttonSecondaryActiveBorderColor: theme.primaryColor700,
  buttonSecondaryBackgroundColor: theme.white,
  buttonSecondaryHoverBackgroundColor: theme.white,
  buttonSecondaryActiveBackgroundColor: theme.white,

  linkColor: theme.primaryColor300,
  linkHoverColor: theme.primaryColor500,
  linkActiveColor: theme.primaryColor600,
  linkVisitedColor: theme.primaryColor700,

  horizontalNavBarSelectedColor: theme.primaryColor500,
  horizontalNavLinkSelectedColor: theme.primaryColor500,
  horizontalNavLinkColor,
  horizontalNavLinkHoverColor,
  horizontalNavLinkActiveColor,

  spinnerPrimaryColor: theme.primaryColor500,

  progressBarFillColor: theme.primaryColor500,

  calendarDateTextColor: theme.primaryColor500,
  calendarDateTextHoverColor: calendarDayHoverColor,
  calendarDateTextActiveColor: calendarDayActiveColor,
  calendarDateTextFocusColor: theme.primaryColor500,
  calendarDateTextSelectedColor: theme.white,
  calendarDateSelectedBackgroundColor: theme.primaryColor700,
  calendarDateFocusedBorderColor: theme.primaryColor500,
  calendarNudgerIconColor: theme.primaryColor500,
  calendarNudgerIconHoverColor: theme.primaryColor600,
  calendarNudgerIconActiveColor: theme.primaryColor700,

  checkboxCheckedColor: theme.primaryColor700,
  radioCheckedColor: theme.primaryColor700,
};

export default bpkCustomTheme;
<|endoftext|>


<commit_before>var async = require('async')
var SALT_WORK_FACTOR = 10
var optional = function (module) {
  try {
    return require(module)
  } catch (e) {}
}
var path = require('path')
var mongoose = require(path.resolve('node_modules', 'mongoose'))
var bcrypt = optional(path.resolve('node_modules', 'bcrypt'))

var compile = function (type) {
  var populate = type.populate = []
  type.hasNested = false
  async.each(type.fields, function (field, cb) {
    if (field.type && field.type.typeName && field.typeName !== 'TypeField') {
      type.hasNested = true
      populate.push({
        path: field.domainName,
        model: field.type.typeName,
        select: field.type.fields.join(' ')
      })
      compile(field.type)
      cb()
    }
  })
}
var converter = module.exports = {
  obscure: function (data, cb) {
    return bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
      if (err) return cb(err)
      bcrypt.hash(data, salt, cb)
    })
  },
  Type: function Type (typeName, fields, options) {
    this.typeName = typeName
    this.fields = fields
    this.hasId = options.hasId
    this.keys = options.keys
    this.discriminator = options.discriminator
  },
  Field: function Field (dtoName, domainName, typeName, type, meta) {
    this.typeName = typeName
    this.dtoName = dtoName
    this.domainName = domainName
    this.type = type
    this.meta = meta || {}
    this.toString = function () {
      return domainName
    }
    this.valueToDto = function (data, cb) {
      switch (typeName) {
        case 'AssociationEnd':
        case 'EntityReferenceField':
        case 'TypeField':
          if (data == null) {
            return cb(null, null)
          } else if (data._id) {
            return cb(null, data._id)
          } else {
            return cb(null, data)
          }
        default:
          if (meta && meta.obscured) {
            return cb(null, null)
          }
          return cb(null, data)
      }
    }
    this.valueFromDto = function (data, cb) {
      // only set if data present (you are changing it).
      if (this.meta.obscured && data) {
        return converter.obscure(data, cb)
      }
      var dateParse = function (data) {
        if (data instanceof Date) {
          return data
        } else if (typeof data === 'string') {
          return new Date(data)
        }
        return data
      }
      var mParseInt = function (v) {
        return parseInt(v)
      }
      switch (typeName) {
        case 'BooleanField':
          var i = parseInt(data)
          if (!data) {
            return cb(null, false)
          } else if (!isNaN(i)) {
            return cb(null, !!i)
          } else {
            var b = data.toString().toLowerCase() === 'true'
            return cb(null, b)
          }
        case 'DateField':
          if (Array.isArray(data)) {
            return cb(null, data.map(dateParse))
          } else {
            return cb(null, dateParse(data))
          }
        case 'NumericField':
        case 'PriceField':
        case 'Amountield':
          if (Array.isArray(data)) {
            return cb(null, data.map(parseFloat))
          } else if (isNaN(data)) {
            return cb(null, parseFloat(data))
          } else {
            return cb(null, data)
          }
        case 'IntegerField':
        case 'CountField':
          if (Array.isArray(data)) {
            return cb(null, data.map(mParseInt))
          } else if (isNaN(data)) {
            return cb(null, parseInt(data))
          } else {
            return cb(null, data)
          }
        case 'AssociationEnd':
        case 'EntityReferenceField':
          if (data == null) {
            return cb(null, null)
          } else if (data._id) {
            return cb(null, data._id)
          } else {
            return cb(null, data)
          }
      }
      return cb(null, data)
    }
    this.queryFrom = function (value, cb) {
      var that = this
      // eslint-disable-next-line handle-callback-err
      this.valueFromDto(value, function (err, value) {
        if ((that.typeName === 'StringField' || that.typeName === 'ShortIdField' ||
          ((that.typeName === 'AssociationEnd' || that.typeName === 'EntityReferenceField') && !that.type)) && value.match && value.match(/^\/.*\/$/)) {
          cb(null, new RegExp(value.substr(1, value.length - 2)))
        } else {
          cb(null, value)
        }
      })
    }
  },
  types: {},
  toDto: function (typeName, domain, callback) {
    converter.doToDto(converter.types[ typeName ], domain, callback)
  },
  fromDto: function (typeName, dto, callback) {
    converter.doFromDto(converter.types[ typeName ], dto, callback)
  },
  toQuery: function (typeName, dto, callback) {
    converter.doToQuery(converter.types[ typeName ], dto, {}, '', callback)
  },
  doToDto: function (type, domain, callback) {
    if (domain == null) {
      return callback()
    }
    if (type == null) {
      return callback(null, domain)
    }
    if (type.hasNested) {
      return mongoose.model(type.typeName).populate(domain, type.populate, function (err, domain) {
        if (err) {
          callback(err)
        } else {
          converter.doToDtoPossiblyArray(type, domain, callback)
        }
      })
    } else {
      return converter.doToDtoPossiblyArray(type, domain, callback)
    }
  },
  doFromDto: function (type, dto, callback) {
    if (dto instanceof Array) {
      return async.mapSeries(dto, function (elem, cb) {
        converter.doFromDtoSingle(type, elem, cb)
      }, callback)
    } else {
      return converter.doFromDtoSingle(type, dto, callback)
    }
  },
  doToQuery: function (type, dto, query, path, callback) {
    if (dto instanceof Array) {
      var index = 0
      return async.mapSeries(dto, function (elem, cb) {
        // XXX adding and removing the .index is probably going to confuse people
        converter.doToQuerySingle(type, elem, query, path + ((dto.length > 1) ? '.' + (index++) + '.' : '.'), cb)
      }, function (err) {
        callback(err, query)
      })
    } else {
      return converter.doToQuerySingle(type, dto, query, path, function (err) {
        callback(err, query)
      })
    }
  },
  doFromDtoSingle: function (type, dto, callback) {
    if (dto == null) {
      return callback(null, null)
    }
    // any type!?
    if (!type) {
      return callback(null, dto)
    }
    var domain = type.typeName ? new (mongoose.models[ type.typeName ])() : {}
    if (dto._id) {
      domain._id = dto._id
    }
    return async.each(type.fields, function (field, cb) {
      var value = dto[ field.dtoName ]
      if (field.meta.obscured && value == null) {
        delete domain[ field.domainName ]
        return cb()
      } else if (field.type) {
        if (typeof value === 'object' && !(value instanceof mongoose.Types.ObjectId)) {
          converter.doFromDto(field.type, value, function (err, data) {
            domain[ field.domainName ] = data
            return cb(err)
          })
        } else {
          domain[ field.domainName ] = value
          cb()
        }
      } else if (value !== undefined) {
        return field.valueFromDto(value, function (err, value) {
          domain[ field.domainName ] = value
          return cb(err)
        })
      } else {
        cb()
      }
    }, function (err) {
      return callback(err, domain)
    })
  },
  doToQuerySingle: function (type, dto, query, path, callback) {
    if (dto == null) {
      return callback(null, query)
    } else if (type != null) {
      if (dto._id && path.length) {
        query[ path.replace(/\.$/, '') ] = dto._id
      } else if (dto._id) {
        query._id = dto._id
      }
      return async.each(type.fields, function (field, cb) {
        var value = dto[ field.dtoName ]
        var name = type.keys[ field.domainName ] ? '_id' : field.domainName
        var nestType = field.type
        var fields = typeof value === 'object' ? Object.keys(value).join(',') : ''
        if (fields.match(/(^\$)|(,\$)/)) {
          query[ path + name ] = value
          return cb()
        } else if (value instanceof Array && nestType) {
          converter.doToQuery(nestType, value, query, path + name, function (err) {
            return cb(err)
          })
        } else {
          if (typeof value === 'object' && nestType) {
            return converter.doToQuerySingle(nestType, value, query, path + name + '.', function (err) {
              return cb(err)
            })
          } else if (value != null) {
            return field.queryFrom(value, function (err, value) {
              query[ path + name ] = value
              return cb(err)
            })
          }
          return cb()
        }
      }, function (err) {
        return callback(err, query)
      })
    } else {
      callback()
    }
  },
  doToDtoPossiblyArray: function (type, domains, callback) {
    if (domains instanceof Array) {
      var dtos = []
      return async.eachSeries(domains, function (domain, cb) {
        converter.doToDtoSingle(type, domain, function (err, data) {
          dtos.push(data)
          return cb(err)
        })
      }, function (err) {
        return callback(err, dtos)
      })
    } else {
      return converter.doToDtoSingle(type, domains, callback)
    }
  },
  doToDtoSingle: function (type, domain, callback) {
    var dto = {}
    var fields = type.fields
    if (domain == null) {
      return callback(null)
    }
    if (domain._id) {
      dto._id = domain._id
    }
    if (domain.__t) {
      dto.__t = domain.__t
    }
    return async.each(fields, function (field, cb) {
      var fieldData = domain[ field.domainName ]
      if (field.type) {
        converter.doToDto(field.type, fieldData, function (err, data) {
          dto[ field.dtoName ] = data
          return cb(err)
        })
      } else {
        return field.valueToDto(fieldData, function (err, value) {
          dto[ field.dtoName ] = value
          return cb(err)
        })
      }
    }, function (err) {
      return callback(err, dto)
    })
  },
  registerType: function (name, type) {
    converter.types[ name ] = type
    compile(type)
  },
  /**
   * Sandwiches work between DTO conversions. The algorithm is as follows.
   *

   *
The given DTO is converted to the given domain object given by
   * type.

   *
If conversion fails, cb is immediately called with the
   * error.

   *
If conversion succeeds, fn is called with the converted
   * domain object and a completion callback of the form
   * function(err, domainOut).

   *
If fn fails, then the given callback should be invoked
   * with the error.

   *
If fn succeeds, then the given callback should be
   * invoked with a falsey error value and the desired outbound domain object.

   *
The outbound domain object is converted back to a DTO and
   * cb is called with error (if there was one) and the outbound
   * dto (if there was no error).

   *

   *
   * @param type
   *          The fully qualified name of the type used by the converter.
   * @param dtoIn
   *          The inbound data as a DTO.
   * @param fn
   *          A function representing the domain work to be done. Signature is
   *          function(domainIn, callback) where callback is of
   *          the form function(err, domainOut). The function
   *          fn must call callback to signal
   *          completion of work, passing an error if one occurred or a falsey
   *          value and the domain object to be converted to a DTO, if an error
   *          didn't occur.
   * @param cb
   *          A completion callback of the form <codeLfunction(err, dtoOut)
   *          where dtoOut is the result of converting the domain
   *          object given to fn's callback.
   */
  sandwich: function (type, dtoIn, fn, cb) {
    converter.from(type, dtoIn, function (errIn, domainIn) {
      if (errIn) return cb(errIn)
      fn(domainIn, function (errFn, domainOut) {
        if (errFn) return cb(errFn)
        converter.to(type, domainOut, function (errOut, dtoOut) {
          cb(errOut, dtoOut)
        })
      })
    })
  }
}
converter.Type.prototype = {
  find: function(query, callback) {
    mongoose.model(this.typeName).find(query, function(err, data) {
      converter.doToDto(this,data,callback);
    });
  },
  findOne:function(query, callback) {
    mongoose.model(this.typeName).findOne(query, function(err, data) {
      converter.doFromDto(this, data, callback);
    });
  }
}
converter.to = converter.toDto
converter.from = converter.fromDto
<commit_msg>standard<commit_after>var async = require('async')
var SALT_WORK_FACTOR = 10
var optional = function (module) {
  try {
    return require(module)
  } catch (e) {
  }
}
var path = require('path')
var mongoose = require(path.resolve('node_modules', 'mongoose'))
var bcrypt = optional(path.resolve('node_modules', 'bcrypt'))

var compile = function (type) {
  var populate = type.populate = []
  type.hasNested = false
  async.each(type.fields, function (field, cb) {
    if (field.type && field.type.typeName && field.typeName !== 'TypeField') {
      type.hasNested = true
      populate.push({
        path: field.domainName,
        model: field.type.typeName,
        select: field.type.fields.join(' ')
      })
      compile(field.type)
      cb()
    }
  })
}
var converter = module.exports = {
  obscure: function (data, cb) {
    return bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
      if (err)
        return cb(err)
      bcrypt.hash(data, salt, cb)
    })
  },
  Type: function Type (typeName, fields, options) {
    this.typeName = typeName
    this.fields = fields
    this.hasId = options.hasId
    this.keys = options.keys
    this.discriminator = options.discriminator
  },
  Field: function Field (dtoName, domainName, typeName, type, meta) {
    this.typeName = typeName
    this.dtoName = dtoName
    this.domainName = domainName
    this.type = type
    this.meta = meta || {}
    this.toString = function () {
      return domainName
    }
    this.valueToDto = function (data, cb) {
      switch (typeName) {
        case 'AssociationEnd':
        case 'EntityReferenceField':
        case 'TypeField':
          if (data == null) {
            return cb(null, null)
          } else if (data._id) {
            return cb(null, data._id)
          } else {
            return cb(null, data)
          }
        default:
          if (meta && meta.obscured) {
            return cb(null, null)
          }
          return cb(null, data)
      }
    }
    this.valueFromDto = function (data, cb) {
      // only set if data present (you are changing it).
      if (this.meta.obscured && data) {
        return converter.obscure(data, cb)
      }
      var dateParse = function (data) {
        if (data instanceof Date) {
          return data
        } else if (typeof data === 'string') {
          return new Date(data)
        }
        return data
      }
      var mParseInt = function (v) {
        return parseInt(v)
      }
      switch (typeName) {
        case 'BooleanField':
          var i = parseInt(data)
          if (!data) {
            return cb(null, false)
          } else if (!isNaN(i)) {
            return cb(null, !!i)
          } else {
            var b = data.toString().toLowerCase() === 'true'
            return cb(null, b)
          }
        case 'DateField':
          if (Array.isArray(data)) {
            return cb(null, data.map(dateParse))
          } else {
            return cb(null, dateParse(data))
          }
        case 'NumericField':
        case 'PriceField':
        case 'Amountield':
          if (Array.isArray(data)) {
            return cb(null, data.map(parseFloat))
          } else if (isNaN(data)) {
            return cb(null, parseFloat(data))
          } else {
            return cb(null, data)
          }
        case 'IntegerField':
        case 'CountField':
          if (Array.isArray(data)) {
            return cb(null, data.map(mParseInt))
          } else if (isNaN(data)) {
            return cb(null, parseInt(data))
          } else {
            return cb(null, data)
          }
        case 'AssociationEnd':
        case 'EntityReferenceField':
          if (data == null) {
            return cb(null, null)
          } else if (data._id) {
            return cb(null, data._id)
          } else {
            return cb(null, data)
          }
      }
      return cb(null, data)
    }
    this.queryFrom = function (value, cb) {
      var that = this
      // eslint-disable-next-line handle-callback-err
      this
          .valueFromDto(
              value,
              function (err, value) {
                if ((that.typeName === 'StringField' || that.typeName === 'ShortIdField' || ((that.typeName === 'AssociationEnd' || that.typeName === 'EntityReferenceField') && !that.type))
                    && value.match && value.match(/^\/.*\/$/)) {
                  cb(null, new RegExp(value.substr(1, value.length - 2)))
                } else {
                  cb(null, value)
                }
              })
    }
  },
  types: {},
  toDto: function (typeName, domain, callback) {
    converter.doToDto(converter.types[ typeName ], domain, callback)
  },
  fromDto: function (typeName, dto, callback) {
    converter.doFromDto(converter.types[ typeName ], dto, callback)
  },
  toQuery: function (typeName, dto, callback) {
    converter.doToQuery(converter.types[ typeName ], dto, {}, '', callback)
  },
  doToDto: function (type, domain, callback) {
    if (domain == null) {
      return callback()
    }
    if (type == null) {
      return callback(null, domain)
    }
    if (type.hasNested) {
      return mongoose.model(type.typeName).populate(domain, type.populate, function (err, domain) {
        if (err) {
          callback(err)
        } else {
          converter.doToDtoPossiblyArray(type, domain, callback)
        }
      })
    } else {
      return converter.doToDtoPossiblyArray(type, domain, callback)
    }
  },
  doFromDto: function (type, dto, callback) {
    if (dto instanceof Array) {
      return async.mapSeries(dto, function (elem, cb) {
        converter.doFromDtoSingle(type, elem, cb)
      }, callback)
    } else {
      return converter.doFromDtoSingle(type, dto, callback)
    }
  },
  doToQuery: function (type, dto, query, path, callback) {
    if (dto instanceof Array) {
      var index = 0
      return async.mapSeries(dto, function (elem, cb) {
        // XXX adding and removing the .index is probably going to confuse
        // people
        converter.doToQuerySingle(type, elem, query, path + ((dto.length > 1) ? '.' + (index++) + '.' : '.'), cb)
      }, function (err) {
        callback(err, query)
      })
    } else {
      return converter.doToQuerySingle(type, dto, query, path, function (err) {
        callback(err, query)
      })
    }
  },
  doFromDtoSingle: function (type, dto, callback) {
    if (dto == null) {
      return callback(null, null)
    }
    // any type!?
    if (!type) {
      return callback(null, dto)
    }
    var domain = type.typeName ? new (mongoose.models[ type.typeName ])() : {}
    if (dto._id) {
      domain._id = dto._id
    }
    return async.each(type.fields, function (field, cb) {
      var value = dto[ field.dtoName ]
      if (field.meta.obscured && value == null) {
        delete domain[ field.domainName ]
        return cb()
      } else if (field.type) {
        if (typeof value === 'object' && !(value instanceof mongoose.Types.ObjectId)) {
          converter.doFromDto(field.type, value, function (err, data) {
            domain[ field.domainName ] = data
            return cb(err)
          })
        } else {
          domain[ field.domainName ] = value
          cb()
        }
      } else if (value !== undefined) {
        return field.valueFromDto(value, function (err, value) {
          domain[ field.domainName ] = value
          return cb(err)
        })
      } else {
        cb()
      }
    }, function (err) {
      return callback(err, domain)
    })
  },
  doToQuerySingle: function (type, dto, query, path, callback) {
    if (dto == null) {
      return callback(null, query)
    } else if (type != null) {
      if (dto._id && path.length) {
        query[ path.replace(/\.$/, '') ] = dto._id
      } else if (dto._id) {
        query._id = dto._id
      }
      return async.each(type.fields, function (field, cb) {
        var value = dto[ field.dtoName ]
        var name = type.keys[ field.domainName ] ? '_id' : field.domainName
        var nestType = field.type
        var fields = typeof value === 'object' ? Object.keys(value).join(',') : ''
        if (fields.match(/(^\$)|(,\$)/)) {
          query[ path + name ] = value
          return cb()
        } else if (value instanceof Array && nestType) {
          converter.doToQuery(nestType, value, query, path + name, function (err) {
            return cb(err)
          })
        } else {
          if (typeof value === 'object' && nestType) {
            return converter.doToQuerySingle(nestType, value, query, path + name + '.', function (err) {
              return cb(err)
            })
          } else if (value != null) {
            return field.queryFrom(value, function (err, value) {
              query[ path + name ] = value
              return cb(err)
            })
          }
          return cb()
        }
      }, function (err) {
        return callback(err, query)
      })
    } else {
      callback()
    }
  },
  doToDtoPossiblyArray: function (type, domains, callback) {
    if (domains instanceof Array) {
      var dtos = []
      return async.eachSeries(domains, function (domain, cb) {
        converter.doToDtoSingle(type, domain, function (err, data) {
          dtos.push(data)
          return cb(err)
        })
      }, function (err) {
        return callback(err, dtos)
      })
    } else {
      return converter.doToDtoSingle(type, domains, callback)
    }
  },
  doToDtoSingle: function (type, domain, callback) {
    var dto = {}
    var fields = type.fields
    if (domain == null) {
      return callback(null)
    }
    if (domain._id) {
      dto._id = domain._id
    }
    if (domain.__t) {
      dto.__t = domain.__t
    }
    return async.each(fields, function (field, cb) {
      var fieldData = domain[ field.domainName ]
      if (field.type) {
        converter.doToDto(field.type, fieldData, function (err, data) {
          dto[ field.dtoName ] = data
          return cb(err)
        })
      } else {
        return field.valueToDto(fieldData, function (err, value) {
          dto[ field.dtoName ] = value
          return cb(err)
        })
      }
    }, function (err) {
      return callback(err, dto)
    })
  },
  registerType: function (name, type) {
    converter.types[ name ] = type
    compile(type)
  },
  /**
   * Sandwiches work between DTO conversions. The algorithm is as follows.
   *

   *
The given DTO is converted to the given domain object given by
   * type.

   *
If conversion fails, cb is immediately called with the
   * error.

   *
If conversion succeeds, fn is called with the converted
   * domain object and a completion callback of the form
   * function(err, domainOut).

   *
If fn fails, then the given callback should be invoked
   * with the error.

   *
If fn succeeds, then the given callback should be
   * invoked with a falsey error value and the desired outbound domain object.

   *
The outbound domain object is converted back to a DTO and
   * cb is called with error (if there was one) and the outbound
   * dto (if there was no error).

   *

   *
   * @param type
   *          The fully qualified name of the type used by the converter.
   * @param dtoIn
   *          The inbound data as a DTO.
   * @param fn
   *          A function representing the domain work to be done. Signature is
   *          function(domainIn, callback) where callback is of
   *          the form function(err, domainOut). The function
   *          fn must call callback to signal
   *          completion of work, passing an error if one occurred or a falsey
   *          value and the domain object to be converted to a DTO, if an error
   *          didn't occur.
   * @param cb
   *          A completion callback of the form <codeLfunction(err, dtoOut)
   *          where dtoOut is the result of converting the domain
   *          object given to fn's callback.
   */
  sandwich: function (type, dtoIn, fn, cb) {
    converter.from(type, dtoIn, function (errIn, domainIn) {
      if (errIn)
        return cb(errIn)
      fn(domainIn, function (errFn, domainOut) {
        if (errFn)
          return cb(errFn)
        converter.to(type, domainOut, function (errOut, dtoOut) {
          cb(errOut, dtoOut)
        })
      })
    })
  }
}
converter.Type.prototype = {
  find: function (query, callback) {
    mongoose.model(this.typeName).find(query, function (err, data) {
      converter.doToDto(this, data, callback)
    })
  },
  findOne: function (query, callback) {
    mongoose.model(this.typeName).findOne(query, function (err, data) {
      converter.doFromDto(this, data, callback)
    })
  }
}
converter.to = converter.toDto
converter.from = converter.fromDto
<|endoftext|>


<commit_before>"use strict";app.component("eeaFormValidation",{template:'

',bindings:{scp:"="},controller:["$translate",function(t){var i=this;this.$onInit=function(){var n=$("eea-form-testing").length?4e3:10;setTimeout(function(){i.validate(t),$(".rowbutton").click(function(){i.validate(t)}),$(".deleterowbutton").click(function(){i.validate(t)})},n)},this.validate=function(t){$("#eeavalidation").html("");var n='Remaining fields:

';$("form.eeaform").each(function(i,e){$(this).find(".formitem :input").each(function(i,e){var o=e.type;if(o&&"submit"!==o){e=$(e);var a=e.val();if(!a){var l=e.attr("name"),r=l.split("$"),c=r[1],d=r[0];n+="
Group "+c+"
",n+=''+t.instant("labels."+d)+"
",n+=(t.instant(e.attr("def"))||"")+"
",n+='<button style="padding:2px;min-width:auto;font-size:11px;width:24px;max-width:24px;height:24px;" onclick=\''+l+".focus()'>Go</button>

"}}}),$("#eeavalidation").html(n+"
")}),$(".formitem :input").change(function(){i.validate(t)}),$(".rowbutton").click(function(){i.validate(t),setTimeout(function(){$(".deleterowbutton").click(function(){i.validate(t)})},100)})}}]});<commit_msg>Added/fixed event listener for Add/Remove Form Row to EEA Form Validation Component<commit_after>"use strict";app.component("eeaFormValidation",{template:'

',bindings:{scp:"="},controller:["$translate",function(t){var i=this;this.$onInit=function(){var n=$("eea-form-testing").length?4e3:10;setTimeout(function(){i.validate(t),$(".formitem :input").change(function(){i.validate(t)}),$(".rowbutton").click(function(){i.validate(t)}),$(".deleterowbutton").click(function(){i.validate(t)})},n)},this.validate=function(t){$("#eeavalidation").html("");var n='Remaining fields:

';$("form.eeaform").each(function(i,e){$(this).find(".formitem :input").each(function(i,e){var o=e.type;if(o&&"submit"!==o){e=$(e);var a=e.val();if(!a){var l=e.attr("name"),r=l.split("$"),c=r[1],u=r[0];n+="
Group "+c+"
",n+=''+t.instant("labels."+u)+"
",n+=(t.instant(e.attr("def"))||"")+"
",n+='<button style="padding:2px;min-width:auto;font-size:11px;width:24px;max-width:24px;height:24px;" onclick=\''+l+".focus()'>Go</button>

"}}}),$("#eeavalidation").html(n+"
")}),$(".formitem :input").change(function(){i.validate(t)}),$(".rowbutton").click(function(){i.validate(t),setTimeout(function(){$(".deleterowbutton").click(function(){i.validate(t)})},100)})}}]});<|endoftext|>


<commit_before>"use strict";

var oTable;
var colHdrs;     // e.g: ['sTitle': 'Testcase', 'sTitle': 'Env', ... ]
var rowHdrs;       // e.g: ['mixed-2suv', 'lucky6', ...]
var BASELINE = "1.8.1-938-rel-enterprise";
var WARNING = 0.1;
var ERROR = 0.3;

function Settings(testcase, metric) {
    this.testcase = testcase;
    this.metric = metric;
    this.baseline = BASELINE;
    this.error = ERROR;
    this.warning = WARNING;
}

function getSettings(settings) {
    /*
     * Get user defined settings
     */
    $.get('/litmus/get/settings',
        {'testcase': settings.testcase, 'metric': settings.metric},
        function(data) {
            settings.error = data.error;
            settings.warning = data.warning;
            settings.baseline = data.baseline;
        }, 'json');
}

function getAllTags() {
    $.get('/litmus/get/tags',
        function(data) {
            $.each(data, function(i, v) {
                // input(type='radio', name='tag', onclick="showResults('');", id="2.0.1")label(for="2.0.1") 2.0.1
                var button = "<input type='radio' name='tag' onclick=\"showResults('" + v + "');\" id='"
                             + v.replace(/\./g, '-')  + "'>" + v + "";
                $('#tag').append(button);
            });
            $(function() {
                $("#tag").buttonset();
            });
        }, 'json');

}

function showResults(tag) {
    var url, oTable;
    if (tag) {
        url = '/litmus/get?tag=';
    } else {
        url = '/litmus/get?';
    }
    $.get(url + tag, { },
        function(data) {
            processData(data);
            renderTable(data);
            applyErrorRanges();
        }, 'json');
}

function changeColors(row, vals, error, warning) {
    /**
     * Change cell colors based on the baseline values
     */
    return function(data) {
        if (data.length === 1) {
            return;
        }
        var baseval = data[1][4];
        $.each(vals.slice(4), function(j, v) {
            v = parseInt(v);
            $(row).find('td').eq(j+4).removeAttr("style");
            if (!isNaN(baseval) && !isNaN(v)) {
                var delta = (v - baseval) / baseval;
                if (Math.abs(error) < Math.abs(warning)) {
                    console.error("invalid error/warning ranges");
                    return;
                }
                if ((delta > error && error > 0) ||
                    (delta < error && error < 0)) {
                    $(row).find('td').eq(j+4).css("background-color","red");
                } else if ((delta > warning && delta < error) ||
                    (delta < warning && delta > error)) {
                    $(row).find('td').eq(j+4).css("background-color","yellow");
                }
            }
        });
    };
}
function applyErrorRanges() {
    /*
     * Apply error range check for each cell
     *
     * If data falls out of the range, turns cell to red
     * Accept negative ranges
     */
    oTable.$('tr').each(function() {
        var row = this;
        var vals = oTable.fnGetData(this);
        var settings = new Settings(vals[0], vals[2]);
        getSettings(settings);
        var uri = '/litmus/get';
        var criteria = {'testcase': settings.testcase,
                        'metric': settings.metric,
                        'build': settings.baseline,
                        'env': vals[1]};
        $.get(uri, criteria,
              changeColors(row, vals, settings.error, settings.warning),
              'json');
    });
}

function processData(data) {
    /*
     * Process json data coming from the server
     * Current implementation retrieves info only
     */
    colHdrs = [];
    rowHdrs = [];
    $.each(data[0], function(i, v) {
        colHdrs[i] = {'sTitle': v};
    });

    $.each(data.slice(1), function(i, v) {
        rowHdrs[i] = v[0];
    });

    return data;
}

function renderTable(data) {
    /*
     * Render table with the given data
     */

    if (oTable) {
        oTable.fnDestroy();
        $("thead").remove();
    }

    oTable = $('#litmus table').dataTable({
        "sDom": 'Tlfrtip',
        'bProcessing': true,
        'bPaginate': true,
        'sPaginationType': 'full_numbers',
        'aaData': data.slice(1),
        'aoColumns': colHdrs,
        'aaSorting': [[0, 'desc']],
        'bStateSave': true,
        'fnDrawCallback': function() {
            $('#loading').remove();
        },
        'bDestroy': true,
        "bAutoWidth": false
    }).bind('sort', function () {
        applyErrorRanges();
    });

    oTable.$('td').each(function() {
        var pos = oTable.fnGetPosition(this);
        if (pos[1] < 4) {
            return;     // support test results for now
        }
        var testcase= data[pos[0] + 1][0];
        var env = data[pos[0] + 1][1];
        var metric = data[pos[0] + 1][2];
        var build = colHdrs[pos[1]]['sTitle'];
        $(this).qtip({
            content: {
                text: 'Loading...',
                ajax: {
                    url: '../get/comment',
                    type: 'GET',
                    loading: false,
                    data: {'testcase': testcase,
                           'env': env,
                           'build': build,
                           'metric': metric},
                    success: function(data, status) {
                        if ($.trim(data).length === 0) {
                            this.set('content.text', 'Click to edit comment');
                        } else {
                            this.set('content.text', data);
                        }
                    },
                    error: function(response) {
                        console.error(response.responseText);
                        this.set('content.text', 'Click to edit comment');
                    }
                }
            },
            position: {
                at: 'bottom center',
                my: 'top left'
            },
            show: {
                solo: true
            },
            hide: 'unfocus',
            style: {
                classes: 'qtip-shadow'
            },
            events: {
                focus: function(event, api) {
                    $(this).find('.qtip-content').editable( '../post/comment/', {
                        submitdata: function (value, settings) {
                            return {
                                "testcase": testcase,
                                "env": env,
                                "metric": metric,
                                "build": build,
                                "comment": $('input[name=value]').val()
                            };
                        },
                        height: '14px',
                        width: '100%'
                    });
                }
            }
        });

        $(this).spectrum({
            showPalette: true,
            palette: [
                ['red', 'yellow', 'green'],
                ['pink', 'lightyellow', 'lightgreen']
            ],
            localStorageKey: "litmus.dashboard",
            showInput: true,
            change: function(color) {
                $(this).css('background-color', color.toHexString());
            }
        });
    });

    new FixedHeader(oTable);
}
<commit_msg>added white to predefined color selections<commit_after>"use strict";

var oTable;
var colHdrs;     // e.g: ['sTitle': 'Testcase', 'sTitle': 'Env', ... ]
var rowHdrs;       // e.g: ['mixed-2suv', 'lucky6', ...]
var BASELINE = "1.8.1-938-rel-enterprise";
var WARNING = 0.1;
var ERROR = 0.3;

function Settings(testcase, metric) {
    this.testcase = testcase;
    this.metric = metric;
    this.baseline = BASELINE;
    this.error = ERROR;
    this.warning = WARNING;
}

function getSettings(settings) {
    /*
     * Get user defined settings
     */
    $.get('/litmus/get/settings',
        {'testcase': settings.testcase, 'metric': settings.metric},
        function(data) {
            settings.error = data.error;
            settings.warning = data.warning;
            settings.baseline = data.baseline;
        }, 'json');
}

function getAllTags() {
    $.get('/litmus/get/tags',
        function(data) {
            $.each(data, function(i, v) {
                // input(type='radio', name='tag', onclick="showResults('');", id="2.0.1")label(for="2.0.1") 2.0.1
                var button = "<input type='radio' name='tag' onclick=\"showResults('" + v + "');\" id='"
                             + v.replace(/\./g, '-')  + "'>" + v + "";
                $('#tag').append(button);
            });
            $(function() {
                $("#tag").buttonset();
            });
        }, 'json');

}

function showResults(tag) {
    var url, oTable;
    if (tag) {
        url = '/litmus/get?tag=';
    } else {
        url = '/litmus/get?';
    }
    $.get(url + tag, { },
        function(data) {
            processData(data);
            renderTable(data);
            applyErrorRanges();
        }, 'json');
}

function changeColors(row, vals, error, warning) {
    /**
     * Change cell colors based on the baseline values
     */
    return function(data) {
        if (data.length === 1) {
            return;
        }
        var baseval = data[1][4];
        $.each(vals.slice(4), function(j, v) {
            v = parseInt(v);
            $(row).find('td').eq(j+4).removeAttr("style");
            if (!isNaN(baseval) && !isNaN(v)) {
                var delta = (v - baseval) / baseval;
                if (Math.abs(error) < Math.abs(warning)) {
                    console.error("invalid error/warning ranges");
                    return;
                }
                if ((delta > error && error > 0) ||
                    (delta < error && error < 0)) {
                    $(row).find('td').eq(j+4).css("background-color","red");
                } else if ((delta > warning && delta < error) ||
                    (delta < warning && delta > error)) {
                    $(row).find('td').eq(j+4).css("background-color","yellow");
                }
            }
        });
    };
}
function applyErrorRanges() {
    /*
     * Apply error range check for each cell
     *
     * If data falls out of the range, turns cell to red
     * Accept negative ranges
     */
    oTable.$('tr').each(function() {
        var row = this;
        var vals = oTable.fnGetData(this);
        var settings = new Settings(vals[0], vals[2]);
        getSettings(settings);
        var uri = '/litmus/get';
        var criteria = {'testcase': settings.testcase,
                        'metric': settings.metric,
                        'build': settings.baseline,
                        'env': vals[1]};
        $.get(uri, criteria,
              changeColors(row, vals, settings.error, settings.warning),
              'json');
    });
}

function processData(data) {
    /*
     * Process json data coming from the server
     * Current implementation retrieves info only
     */
    colHdrs = [];
    rowHdrs = [];
    $.each(data[0], function(i, v) {
        colHdrs[i] = {'sTitle': v};
    });

    $.each(data.slice(1), function(i, v) {
        rowHdrs[i] = v[0];
    });

    return data;
}

function renderTable(data) {
    /*
     * Render table with the given data
     */

    if (oTable) {
        oTable.fnDestroy();
        $("thead").remove();
    }

    oTable = $('#litmus table').dataTable({
        "sDom": 'Tlfrtip',
        'bProcessing': true,
        'bPaginate': true,
        'sPaginationType': 'full_numbers',
        'aaData': data.slice(1),
        'aoColumns': colHdrs,
        'aaSorting': [[0, 'desc']],
        'bStateSave': true,
        'fnDrawCallback': function() {
            $('#loading').remove();
        },
        'bDestroy': true,
        "bAutoWidth": false
    }).bind('sort', function () {
        applyErrorRanges();
    });

    oTable.$('td').each(function() {
        var pos = oTable.fnGetPosition(this);
        if (pos[1] < 4) {
            return;     // support test results for now
        }
        var testcase= data[pos[0] + 1][0];
        var env = data[pos[0] + 1][1];
        var metric = data[pos[0] + 1][2];
        var build = colHdrs[pos[1]]['sTitle'];
        $(this).qtip({
            content: {
                text: 'Loading...',
                ajax: {
                    url: '../get/comment',
                    type: 'GET',
                    loading: false,
                    data: {'testcase': testcase,
                           'env': env,
                           'build': build,
                           'metric': metric},
                    success: function(data, status) {
                        if ($.trim(data).length === 0) {
                            this.set('content.text', 'Click to edit comment');
                        } else {
                            this.set('content.text', data);
                        }
                    },
                    error: function(response) {
                        console.error(response.responseText);
                        this.set('content.text', 'Click to edit comment');
                    }
                }
            },
            position: {
                at: 'bottom center',
                my: 'top left'
            },
            show: {
                solo: true
            },
            hide: 'unfocus',
            style: {
                classes: 'qtip-shadow'
            },
            events: {
                focus: function(event, api) {
                    $(this).find('.qtip-content').editable( '../post/comment/', {
                        submitdata: function (value, settings) {
                            return {
                                "testcase": testcase,
                                "env": env,
                                "metric": metric,
                                "build": build,
                                "comment": $('input[name=value]').val()
                            };
                        },
                        height: '14px',
                        width: '100%'
                    });
                }
            }
        });

        $(this).spectrum({
            showPalette: true,
            palette: [
                ['white'],
                ['red', 'yellow', 'green'],
                ['pink', 'lightyellow', 'lightgreen']
            ],
            localStorageKey: "litmus.dashboard",
            showInput: true,
            change: function(color) {
                $(this).css('background-color', color.toHexString());
            }
        });
    });

    new FixedHeader(oTable);
}
<|endoftext|>


<commit_before>/**
 * 带有一个占位
 *
 * Created by GUY on 2015/9/11.
 * @class BI.BlankIconTextItem
 * @extends BI.BasicButton
 */
BI.BlankIconTextItem = BI.inherit(BI.BasicButton, {

    _defaultConfig: function () {
        var conf = BI.BlankIconTextItem.superclass._defaultConfig.apply(this, arguments);
        return BI.extend(conf, {
            baseCls: (conf.baseCls || "") + " bi-blank-icon-text-item",
            logic: {
                dynamic: false
            },
            blankWidth: 0,
            iconHeight: null,
            iconWidth: null,
            iconCls: "",
            textHgap: 0,
            textVgap: 0,
            textLgap: 0,
            textRgap: 0
        });
    },

    render: function () {
        var self = this, o = this.options;

        return {
            type: "bi.vertical_adapt",
            columnSize: [o.blankWidth, "fill", o.iconWrapperWidth || o.height],
            items: [{
                type: "bi.layout",
                width: o.blankWidth
            }, {
                type: "bi.label",
                ref: function (_ref) {
                    self.text = _ref;
                },
                cls: "list-item-text",
                textAlign: "left",
                hgap: o.textHgap,
                vgap: o.textVgap,
                lgap: o.textLgap,
                rgap: o.textRgap,
                text: o.text,
                value: o.value,
                keyword: o.keyword,
                height: o.height
            }, {
                type: "bi.icon_label",
                cls: o.iconCls,
                width: o.iconWrapperWidth || o.height,
                height: o.height,
                iconWidth: o.iconWidth,
                iconHeight: o.iconHeight
            }]
        };
    },

    doClick: function () {
        BI.BlankIconTextItem.superclass.doClick.apply(this, arguments);
        if (this.isValid()) {
            this.fireEvent(BI.BlankIconTextItem.EVENT_CHANGE, this.getValue(), this);
        }
    },

    setValue: function () {
        if (!this.isReadOnly()) {
            this.text.setValue.apply(this.text, arguments);
        }
    },

    getValue: function () {
        return this.text.getValue();
    },

    setText: function () {
        this.text.setText.apply(this.text, arguments);
    },

    getText: function () {
        return this.text.getText();
    },

    doRedMark: function () {
        this.text.doRedMark.apply(this.text, arguments);
    },

    unRedMark: function () {
        this.text.unRedMark.apply(this.text, arguments);
    },

    doHighLight: function () {
        this.text.doHighLight.apply(this.text, arguments);
    },

    unHighLight: function () {
        this.text.unHighLight.apply(this.text, arguments);
    }
});
BI.BlankIconTextItem.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.blank_icon_text_item", BI.BlankIconTextItem);
<commit_msg>无JIRA任务 icon和text位置反了<commit_after>/**
 * 带有一个占位
 *
 * Created by GUY on 2015/9/11.
 * @class BI.BlankIconTextItem
 * @extends BI.BasicButton
 */
BI.BlankIconTextItem = BI.inherit(BI.BasicButton, {

    _defaultConfig: function () {
        var conf = BI.BlankIconTextItem.superclass._defaultConfig.apply(this, arguments);
        return BI.extend(conf, {
            baseCls: (conf.baseCls || "") + " bi-blank-icon-text-item",
            logic: {
                dynamic: false
            },
            blankWidth: 0,
            iconHeight: null,
            iconWidth: null,
            iconCls: "",
            textHgap: 0,
            textVgap: 0,
            textLgap: 0,
            textRgap: 0
        });
    },

    render: function () {
        var self = this, o = this.options;

        return {
            type: "bi.vertical_adapt",
            columnSize: [o.blankWidth, o.iconWrapperWidth || o.height, "fill"],
            items: [{
                type: "bi.layout",
                width: o.blankWidth
            }, {
                type: "bi.icon_label",
                cls: o.iconCls,
                width: o.iconWrapperWidth || o.height,
                height: o.height,
                iconWidth: o.iconWidth,
                iconHeight: o.iconHeight
            }, {
                type: "bi.label",
                ref: function (_ref) {
                    self.text = _ref;
                },
                cls: "list-item-text",
                textAlign: "left",
                hgap: o.textHgap,
                vgap: o.textVgap,
                lgap: o.textLgap,
                rgap: o.textRgap,
                text: o.text,
                value: o.value,
                keyword: o.keyword,
                height: o.height
            }]
        };
    },

    doClick: function () {
        BI.BlankIconTextItem.superclass.doClick.apply(this, arguments);
        if (this.isValid()) {
            this.fireEvent(BI.BlankIconTextItem.EVENT_CHANGE, this.getValue(), this);
        }
    },

    setValue: function () {
        if (!this.isReadOnly()) {
            this.text.setValue.apply(this.text, arguments);
        }
    },

    getValue: function () {
        return this.text.getValue();
    },

    setText: function () {
        this.text.setText.apply(this.text, arguments);
    },

    getText: function () {
        return this.text.getText();
    },

    doRedMark: function () {
        this.text.doRedMark.apply(this.text, arguments);
    },

    unRedMark: function () {
        this.text.unRedMark.apply(this.text, arguments);
    },

    doHighLight: function () {
        this.text.doHighLight.apply(this.text, arguments);
    },

    unHighLight: function () {
        this.text.unHighLight.apply(this.text, arguments);
    }
});
BI.BlankIconTextItem.EVENT_CHANGE = "EVENT_CHANGE";
BI.shortcut("bi.blank_icon_text_item", BI.BlankIconTextItem);
<|endoftext|>