<commit_before>define([
  'angular',
  'lodash',
  'app/core/utils/datemath',
  'app/core/utils/kbn',
  'moment',
  './queryCtrl',
  './directives'
],
function (angular, _, dateMath, kbn) {
  'use strict';

  var module = angular.module('grafana.services');

  module.factory('Warp10Datasource', function($q, $http, templateSrv) {

    function Warp10Datasource(datasource) {
      this.type = 'warp10';
      this.name = datasource.name;
      this.supportMetrics = true;

      this.url = datasource.url;
      this.lastErrors = {};
    }

    // Called once per panel (graph)
    Warp10Datasource.prototype.query = function(options) {

      console.log("Query begin");

      var end = convertToWarp10Time(options.range.to);
      var start = convertToWarp10Time(options.range.from);

      console.log("From: "+start+ " To: "+end);

      var queries = [];

      console.log("Before foreach");

      _.each(options.targets, _.bind(function(target) {

        console.debug("Expre", target.expr);
        console.debug("Backend URL", target.backend);

        queries.push(target);
      }, this));

      console.log("After foreach");

      // No valid targets, return the empty result to save a round trip.
      if (_.isEmpty(queries)) {

        console.log("Empty query");

        var d = $q.defer();
        d.resolve({ data: [] });
        return d.promise;
      }

      var allQueryPromise = _.map(queries, _.bind(function(query) {
        return this.performTimeSeriesQuery(query, start, end);
      }, this));

      var self = this;
      return $q.all(allQueryPromise)
        .then(function(allResponse) {
          var result = [];

          _.each(allResponse, function(response, index) {

            console.log("Response", response);
            if (response.data.type === 'error') {
              self.lastErrors.query = response.data.value;
              throw response.data.value;
            }
            delete self.lastErrors.query;

            if (!isArray(response.data) || (response.data.length != 1)) {
              console.debug("Response isn't an Array or it has more than 1 element", response.data);
              return {};
            }

            var warpscriptJsonResponse = response.data[0];

            console.log("Response data", warpscriptJsonResponse)

            _.each(warpscriptJsonResponse, function(metricData) {
              console.log("Metric data",metricData);

              result.push(transformMetricData(metricData, options.targets[index]));
            });
          });

          return { data: result };
        });
    };

    /***********************************************************************************
    *Puts into the Warpscript script a header to place start and end ont the stack
    ***********************************************************************************/
    Warp10Datasource.prototype.prepareWarpscriptQuery = function(query, start, end) {

      var endISO = convertToISO(end);
      var startISO = convertToISO(start);
      var interval = end - start;

      var warpscriptScript =
            "" + start + " 'start' STORE " + end + " 'end' STORE " +
            "'" + startISO + "' 'startISO' STORE '" + endISO + "' 'endISO' STORE " +
            interval + " 'interval' STORE";
      if (query.expr !== undefined) {
         warpscriptScript += " " + query.expr;
      }
      return warpscriptScript;
    }

    /***********************************************************************************
    * Generate @query Warpscript http query to the Warpscript API entry point
    ***********************************************************************************/
    Warp10Datasource.prototype.performTimeSeriesQuery = function(query, start, end) {

      var warpscriptScript = this.prepareWarpscriptQuery(query, start, end);

      var backend = this.url;
      // If we have defined a backend in the query editor, it takes preecedence
      // over the datasource
      if ((query.backend !== undefined) && (query.backend.length >0)) {
        backend = query.backend;
      }

      while (backend[backend.length-1] === '/') {
        // remove trailing slash
        backend = backend.substr(0, backend.length - 1);
      }

      var url = backend + '/api/v0/exec'

      var options = {
        method: 'POST',
        url: url,
        data: warpscriptScript,
        headers: {
            'Accept': undefined,
            'Content-Type': undefined,
            'X-Warp10-Token': 'token'
        }
      };

      return $http(options);
    };

    /***********************************************************************************
    * Transform from Warpscript JSON to Grafana dps
    ***********************************************************************************/
    function transformMetricData(gts, options) {

      if (!isGts(gts)) {
        console.debug("Response item isn't a gts",gts);
        return;
      }

      var className = gts.c;

      var labels =
        _.map(gts.l, function(value, key){
          return key+"="+value
        }).join(",");

      var metricName = className+"{"+labels+"}"
      var dps = [];

      _.each(gts.v, function(value) {
        // Datapoint format: [ value, label]
        dps.push([value[value.length -1], Math.floor(value[0]/1000)]);
      });

      // Metric format {target: "Label text", datapoints: [ datapoints objects] }

      console.debug({ target: metricName , datapoints: dps });
      return { target: metricName, datapoints: dps };
    }

    /***********************************************************************************
    * Returns true if @value is an Array
    ***********************************************************************************/
    function isArray(value) {
      return value && typeof value === 'object' && value instanceof Array && typeof value.length === 'number'
        && typeof value.splice === 'function' && !(value.propertyIsEnumerable('length'));
    };

    /***********************************************************************************
    * Returns true if @gts is a JSON object version of a GTS
    ***********************************************************************************/
    function isGts(gts) {
      if ((gts.c == null) || (gts.l == null) || (gts.a == null) || (gts.v == null)) {
        return false;
      }
      return true;
    };

    /***********************************************************************************
    * Converts @date into µs since Epoch time (Warpscript tick format)
    ***********************************************************************************/
    function convertToWarp10Time(date) {
      date = dateMath.parse(date);
      return date * 1000;
    }

    /***********************************************************************************
    * Converts @timestamp into ISO 8601 format
    ***********************************************************************************/
    function convertToISO(timestamp) {
      var date = new Date(Math.floor(timestamp/1000));
      return date.toISOString();
    }

    return Warp10Datasource;
  });

});
<commit_msg>Add support for grafana templating in warpscript<commit_after>define([
  'angular',
  'lodash',
  'app/core/utils/datemath',
  'app/core/utils/kbn',
  'moment',
  './queryCtrl',
  './directives'
],
function (angular, _, dateMath, kbn) {
  'use strict';

  var module = angular.module('grafana.services');

  module.factory('Warp10Datasource', function($q, $http, templateSrv) {

    function Warp10Datasource(datasource) {
      this.type = 'warp10';
      this.name = datasource.name;
      this.supportMetrics = true;

      this.url = datasource.url;
      this.lastErrors = {};
    }

    // Called once per panel (graph)
    Warp10Datasource.prototype.query = function(options) {

      console.log("Query begin");

      var end = convertToWarp10Time(options.range.to);
      var start = convertToWarp10Time(options.range.from);

      console.log("From: "+start+ " To: "+end);

      var queries = [];

      console.log("Before foreach");

      _.each(options.targets, _.bind(function(target) {

        console.debug("Expre", target.expr);
        console.debug("Backend URL", target.backend);

        queries.push(target);
      }, this));

      console.log("After foreach");

      // No valid targets, return the empty result to save a round trip.
      if (_.isEmpty(queries)) {

        console.log("Empty query");

        var d = $q.defer();
        d.resolve({ data: [] });
        return d.promise;
      }

      var allQueryPromise = _.map(queries, _.bind(function(query) {
        return this.performTimeSeriesQuery(query, start, end);
      }, this));

      var self = this;
      return $q.all(allQueryPromise)
        .then(function(allResponse) {
          var result = [];

          _.each(allResponse, function(response, index) {

            console.log("Response", response);
            if (response.data.type === 'error') {
              self.lastErrors.query = response.data.value;
              throw response.data.value;
            }
            delete self.lastErrors.query;

            if (!isArray(response.data) || (response.data.length != 1)) {
              console.debug("Response isn't an Array or it has more than 1 element", response.data);
              return {};
            }

            var warpscriptJsonResponse = response.data[0];

            console.log("Response data", warpscriptJsonResponse)

            _.each(warpscriptJsonResponse, function(metricData) {
              console.log("Metric data",metricData);

              result.push(transformMetricData(metricData, options.targets[index]));
            });
          });

          return { data: result };
        });
    };

    /***********************************************************************************
    *Puts into the Warpscript script a header to place start and end ont the stack
    ***********************************************************************************/
    Warp10Datasource.prototype.prepareWarpscriptQuery = function(query, start, end) {

      var endISO = convertToISO(end);
      var startISO = convertToISO(start);
      var interval = end - start;

      var warpscriptScript =
            "" + start + " 'start' STORE " + end + " 'end' STORE " +
            "'" + startISO + "' 'startISO' STORE '" + endISO + "' 'endISO' STORE " +
            interval + " 'interval' STORE";
      _.each(templateSrv.variables, function(variable) {
         warpscriptScript += "\n'" + variable.current.value + "' '"+variable.name+"' STORE";
      });
      if (query.expr !== undefined) {
         warpscriptScript += " " + query.expr;
      }
      return warpscriptScript;
    }

    /***********************************************************************************
    * Generate @query Warpscript http query to the Warpscript API entry point
    ***********************************************************************************/
    Warp10Datasource.prototype.performTimeSeriesQuery = function(query, start, end) {

      var warpscriptScript = this.prepareWarpscriptQuery(query, start, end);

      var backend = this.url;
      // If we have defined a backend in the query editor, it takes preecedence
      // over the datasource
      if ((query.backend !== undefined) && (query.backend.length >0)) {
        backend = query.backend;
      }

      while (backend[backend.length-1] === '/') {
        // remove trailing slash
        backend = backend.substr(0, backend.length - 1);
      }

      var url = backend + '/api/v0/exec'

      var options = {
        method: 'POST',
        url: url,
        data: warpscriptScript,
        headers: {
            'Accept': undefined,
            'Content-Type': undefined,
            'X-Warp10-Token': 'token'
        }
      };

      return $http(options);
    };

    /***********************************************************************************
    * Transform from Warpscript JSON to Grafana dps
    ***********************************************************************************/
    function transformMetricData(gts, options) {

      if (!isGts(gts)) {
        console.debug("Response item isn't a gts",gts);
        return;
      }

      var className = gts.c;

      var labels =
        _.map(gts.l, function(value, key){
          return key+"="+value
        }).join(",");

      var metricName = className+"{"+labels+"}"
      var dps = [];

      _.each(gts.v, function(value) {
        // Datapoint format: [ value, label]
        dps.push([value[value.length -1], Math.floor(value[0]/1000)]);
      });

      // Metric format {target: "Label text", datapoints: [ datapoints objects] }

      console.debug({ target: metricName , datapoints: dps });
      return { target: metricName, datapoints: dps };
    }

    /***********************************************************************************
    * Returns true if @value is an Array
    ***********************************************************************************/
    function isArray(value) {
      return value && typeof value === 'object' && value instanceof Array && typeof value.length === 'number'
        && typeof value.splice === 'function' && !(value.propertyIsEnumerable('length'));
    };

    /***********************************************************************************
    * Returns true if @gts is a JSON object version of a GTS
    ***********************************************************************************/
    function isGts(gts) {
      if ((gts.c == null) || (gts.l == null) || (gts.a == null) || (gts.v == null)) {
        return false;
      }
      return true;
    };

    /***********************************************************************************
    * Converts @date into µs since Epoch time (Warpscript tick format)
    ***********************************************************************************/
    function convertToWarp10Time(date) {
      date = dateMath.parse(date);
      return date * 1000;
    }

    /***********************************************************************************
    * Converts @timestamp into ISO 8601 format
    ***********************************************************************************/
    function convertToISO(timestamp) {
      var date = new Date(Math.floor(timestamp/1000));
      return date.toISOString();
    }

    return Warp10Datasource;
  });

});
<|endoftext|>


<commit_before>module.exports = drainpipe
drainpipe.unwrap = unwrap

function drainpipe(x) {
  var curr = unwrap(x)
  self._drainpipe_chain = true

  function self(fn) {
    if (!arguments.length) return curr

    var args = Array.prototype.slice.call(arguments, 1)
    args.unshift(curr)
    curr = unwrap(fn.apply(fn, args))

    return self
  }

  return self
}

function unwrap(x) {
  return (x || 0)._drainpipe_chain
    ? x()
    : x
}
<commit_msg>support umd<commit_after>;(function() {
  drainpipe.unwrap = unwrap

  function drainpipe(x) {
    var curr = unwrap(x)
    self._drainpipe_chain = true

    function self(fn) {
      if (!arguments.length) return curr

      var args = Array.prototype.slice.call(arguments, 1)
      args.unshift(curr)
      curr = unwrap(fn.apply(fn, args))

      return self
    }

    return self
  }

  function unwrap(x) {
    return (x || 0)._drainpipe_chain
      ? x()
      : x
  }

  if (typeof module != 'undefined') {
    module.exports = drainpipe
  }
  else if (typeof define == 'function' && define.amd) {
    define(function() {
      return drainpipe
    })
  }
  else {
    this.drainpipe = drainpipe
  }
}).call(this);
<|endoftext|>


<commit_before>class Controller {

  constructor () {

    window.DEBUGcontroller = this;

    this.color          = new Color();
    this.help           = new Help(".module-help");
    this.search         = new Search( ".search-input", ".topology-selector", ".search-sets", this.color );
    this.disambiguation = new Disambiguation();
    this.probfilter     = new ProbabilityFilter( ".min-prob-slider", ".min-prob-slider-value" );
    this.textfilter     = new TextFilter( ".filter-select", ".filter-is-not .is", ".filter-text", ".filter-dropdown", ".add-filter", ".filters");
    this.highlighter    = new Highlight( ".highlight-input" );
    this.grouper        = new Grouper( ".grouper-module .table-grouping" );
    this.graph          = new GraphView("graph");
    this.download       = new Download(".download-module button.download");

    this.tablestate     = { zoomed: false, zoomgroup: null };
    this.firstsearch    = true;
    this.interactions   = null;
    this.filtrate       = null;

    $( function() {
      $(".panel-top").resizable({
        handleSelector: ".splitter-horizontal",
        resizeWidth: false
      });
    });
  }

  runSearch() {
    this.hideHelp();
    this.hideTable();
    this.hideGraph();
    this.hideGraphLegend();
    this.hideGraphAbsent();
    this.hideNoResults();
    this.hideTableSpinner();
    this.hideGraphSpinner();

    // Some control modules are hidden until the first search is run. Expose them.
    if ( this.firstsearch ) {
      this.firstsearch = false;
      $('.table-view .messaging-and-controls').css('visibility', 'visible');
      $('.module').css('visibility', 'visible');
      $('.divider').css('visibility', 'visible');
    }

    // If the user has cleared the last search items, go to HELP state
    if ( this.search.sets.length == 0 ) {
      this.showHelp();
      return;
    }

    let topology = GeneDive.search.selectedTopology();
    if ( this.search.sets.length != 2 && ( topology == "2hop" || topology == "3hop" ) ) {
      alertify.notify("2-Hop / 3-Hop requires 2 Genes", "", "3");
      this.showNoResults();
      return;
    }

    if ( topology == "clique" && ( this.search.sets.length > 1 || this.search.sets[0].ids.length > 1 ) ) {
      alertify.notify("Clique search requires a single gene.", "", "3");
      this.showNoResults();
      return;
    }

    let minProb = this.probfilter.getMinimumProbability();
    let ids = this.search.getIds( minProb );

    // It's possible that no results were found from the adjacency matrix
    if ( !ids || ids.length == 0 ) {
      this.showNoResults();
      return;
    };

    // This resets the table view to default
    this.tablestate.zoomed = false;
    this.showSpinners();

    GeneDiveAPI.interactions( ids, minProb, ( interactions ) => {
      this.interactions = JSON.parse( interactions );

      // Check to see if there are any results
      if(this.noResultsFound())
        return;

      this.filterInteractions();
    });
  }

  /* Returns new array of interactions passing the text filters */
  /* IMPORTANT - use this.filtrate, not this.interactions hereafter */
  filterInteractions() {
    if ( !this.spinneractive ) {
      this.hideTable();
      this.hideGraph();
      this.showSpinners();
    }
    this.filtrate = this.textfilter.filterInteractions( this.interactions );
    this.colorInteractions();
  }

  /* Figures out the color(s) for each gene based on topology */
  colorInteractions() {
    this.filtrate = this.color.colorInteractions( this.filtrate );
    this.addSynonyms();
  }

  /* Synonym static method will add mention1_synonym and mention2_synonym to interactions as synonym or null if none needed. */
  addSynonyms() {
    this.filtrate = Synonym.findSynonyms( this.search.sets, this.filtrate );  // Static class
    this.highlightInteractions();
  }

  /* Highlight class adds a highlight property to interactions */
  highlightInteractions() {
    if ( !this.spinneractive ) {
      this.hideTable();
      this.hideGraph();
      this.showSpinners();
    }
    this.filtrate = this.highlighter.highlight( this.filtrate );

    // Check to see if there are any results
    if(this.noResultsFound() == false)
    {
      this.drawTable();
      this.drawGraph();
    }
    this.spinneractive = false;
  }

  drawTable() {
    // We want to create a new table for each iteration as the old one will have prior listener/config/bindings
    $('.table-view table').remove();
    $('.table-view').append($("<table/>").addClass("table table-hover"));

    // First check for zoom condition
    if ( this.tablestate.zoomed ) {
      new TableDetail( ".table-view table", this.filtrate, this.tablestate.zoomgroup );
      this.hideTableSpinner();
      return;
    }

    // Otherwise show the appropriate summary view
    if ( this.grouper.selected() == "gene" ) {
      new TableSummaryGene( ".table-view .table", this.filtrate, ".table-view .topbar .back" );
    } else {
      new TableSummaryArticle( ".table-view table", this.filtrate, ".table-view .topbar .back" );
    }

    this.hideTableSpinner();
  }

  // This will return true if no results are found, and false if some results are found.
  // This will also hide the graphs and tables if no results are found
  noResultsFound(){

    // If there are no interactions, or if there are interactions but the filters return zero results, hide the graphs and tables.
    if ( this.interactions.length === 0 || (this.filtrate !== null && this.filtrate.length === 0))
    {
      this.hideTableSpinner();
      this.hideGraphSpinner();
      this.showNoResults();
      return true;
    }
    this.hideNoResults();
    return false;

  }

  drawGraph() {
    this.graph.draw( this.filtrate, this.search.sets );
    this.hideGraphSpinner();
    this.showGraph();
    this.showGraphLegend();
  }

  hideTable() {
    $('.messaging-and-controls').hide();
    $('.table').hide();
  }

  showTable() {
    $('.messaging-and-controls').show();
    $('.table').show();
  }

  hideGraph() {
    $('#graph').hide();
  }

  showGraph() {
    $('#graph').show();
  }

  showSpinners() {
    $(".spinner").show().css("display", "flex");
  }

  hideTableSpinner() {
    $(".table-rendering-spinner").hide();
  }

  hideGraphSpinner() {
    $(".graph-rendering-spinner").hide();
  }

  showHelp() {
    $(".help").show();
  }

  hideHelp() {
    $(".help").hide();
  }

  showNoResults() {
    $(".no-results").show();
  }

  hideNoResults() {
    $(".no-results").hide();
  }

  showGraphLegend() {
    $(".graph-view .legend").show();
  }

  hideGraphLegend() {
    $(".graph-view .legend").hide();
  }

  hideGraphAbsent() {
    $(".graph-view .absent").hide();
  }

}

let GeneDive = new Controller();

$(document).on('ready', function () {
  $('[data-toggle="tooltip"]').tooltip();

  // Mirror Adjacency Matrix
  for ( let gene in adjacency_matrix ) {
    for ( let interactant in adjacency_matrix[gene] ) {

      if ( !(interactant in adjacency_matrix) ) {
        adjacency_matrix[interactant] = {};
      }

      if ( !(gene in adjacency_matrix[interactant]) ) {
        adjacency_matrix[interactant][gene] = true;
      }

    }
  }

});
<commit_msg>Filters now hide when no searches are made<commit_after>class Controller {

  constructor () {

    window.DEBUGcontroller = this;

    this.color          = new Color();
    this.help           = new Help(".module-help");
    this.search         = new Search( ".search-input", ".topology-selector", ".search-sets", this.color );
    this.disambiguation = new Disambiguation();
    this.probfilter     = new ProbabilityFilter( ".min-prob-slider", ".min-prob-slider-value" );
    this.textfilter     = new TextFilter( ".filter-select", ".filter-is-not .is", ".filter-text", ".filter-dropdown", ".add-filter", ".filters");
    this.highlighter    = new Highlight( ".highlight-input" );
    this.grouper        = new Grouper( ".grouper-module .table-grouping" );
    this.graph          = new GraphView("graph");
    this.download       = new Download(".download-module button.download");

    this.tablestate     = { zoomed: false, zoomgroup: null };
    this.interactions   = null;
    this.filtrate       = null;

    $( function() {
      $(".panel-top").resizable({
        handleSelector: ".splitter-horizontal",
        resizeWidth: false
      });
    });
  }

  runSearch() {
    this.hideHelp();
    this.hideTable();
    this.hideGraph();
    this.hideGraphLegend();
    this.hideGraphAbsent();
    this.hideNoResults();
    this.hideTableSpinner();
    this.hideGraphSpinner();

    // If the user has cleared the last search items, go to HELP state and hide filters. Otherwise, show the filters
    if ( this.search.sets.length == 0 ) {
      this.showHelp();
      this.hideFilters();
      return;
    }
    this.showFilters();

    let topology = GeneDive.search.selectedTopology();
    if ( this.search.sets.length != 2 && ( topology == "2hop" || topology == "3hop" ) ) {
      alertify.notify("2-Hop / 3-Hop requires 2 Genes", "", "3");
      this.showNoResults();
      return;
    }

    if ( topology == "clique" && ( this.search.sets.length > 1 || this.search.sets[0].ids.length > 1 ) ) {
      alertify.notify("Clique search requires a single gene.", "", "3");
      this.showNoResults();
      return;
    }

    let minProb = this.probfilter.getMinimumProbability();
    let ids = this.search.getIds( minProb );

    // It's possible that no results were found from the adjacency matrix
    if ( !ids || ids.length == 0 ) {
      this.showNoResults();
      return;
    };

    // This resets the table view to default
    this.tablestate.zoomed = false;
    this.showSpinners();

    GeneDiveAPI.interactions( ids, minProb, ( interactions ) => {
      this.interactions = JSON.parse( interactions );

      // Check to see if there are any results
      if(this.noResultsFound())
        return;

      this.filterInteractions();
    });
  }

  /* Returns new array of interactions passing the text filters */
  /* IMPORTANT - use this.filtrate, not this.interactions hereafter */
  filterInteractions() {
    if ( !this.spinneractive ) {
      this.hideTable();
      this.hideGraph();
      this.showSpinners();
    }
    this.filtrate = this.textfilter.filterInteractions( this.interactions );
    this.colorInteractions();
  }

  /* Figures out the color(s) for each gene based on topology */
  colorInteractions() {
    this.filtrate = this.color.colorInteractions( this.filtrate );
    this.addSynonyms();
  }

  /* Synonym static method will add mention1_synonym and mention2_synonym to interactions as synonym or null if none needed. */
  addSynonyms() {
    this.filtrate = Synonym.findSynonyms( this.search.sets, this.filtrate );  // Static class
    this.highlightInteractions();
  }

  /* Highlight class adds a highlight property to interactions */
  highlightInteractions() {
    if ( !this.spinneractive ) {
      this.hideTable();
      this.hideGraph();
      this.showSpinners();
    }
    this.filtrate = this.highlighter.highlight( this.filtrate );

    // Check to see if there are any results
    if(this.noResultsFound() == false)
    {
      this.drawTable();
      this.drawGraph();
    }
    this.spinneractive = false;
  }

  drawTable() {
    // We want to create a new table for each iteration as the old one will have prior listener/config/bindings
    $('.table-view table').remove();
    $('.table-view').append($("<table/>").addClass("table table-hover"));

    // First check for zoom condition
    if ( this.tablestate.zoomed ) {
      new TableDetail( ".table-view table", this.filtrate, this.tablestate.zoomgroup );
      this.hideTableSpinner();
      return;
    }

    // Otherwise show the appropriate summary view
    if ( this.grouper.selected() == "gene" ) {
      new TableSummaryGene( ".table-view .table", this.filtrate, ".table-view .topbar .back" );
    } else {
      new TableSummaryArticle( ".table-view table", this.filtrate, ".table-view .topbar .back" );
    }

    this.hideTableSpinner();
  }

  // This will return true if no results are found, and false if some results are found.
  // This will also hide the graphs and tables if no results are found
  noResultsFound(){

    // If there are no interactions, or if there are interactions but the filters return zero results, hide the graphs and tables.
    if ( this.interactions.length === 0 || (this.filtrate !== null && this.filtrate.length === 0))
    {
      this.hideTableSpinner();
      this.hideGraphSpinner();
      this.showNoResults();
      return true;
    }
    this.hideNoResults();
    return false;

  }

  drawGraph() {
    this.graph.draw( this.filtrate, this.search.sets );
    this.hideGraphSpinner();
    this.showGraph();
    this.showGraphLegend();
  }

  hideTable() {
    $('.messaging-and-controls').hide();
    $('.table').hide();
  }

  showTable() {
    $('.messaging-and-controls').show();
    $('.table').show();
  }

  hideGraph() {
    $('#graph').hide();
  }

  showGraph() {
    $('#graph').show();
    this.graph.fit(10);
  }

  showSpinners() {
    $(".spinner").show().css("display", "flex");
  }

  hideTableSpinner() {
    $(".table-rendering-spinner").hide();
  }

  hideGraphSpinner() {
    $(".graph-rendering-spinner").hide();
  }

  showHelp() {
    $(".help").show();
  }

  hideHelp() {
    $(".help").hide();
  }

  showNoResults() {
    $(".no-results").show();
  }

  hideNoResults() {
    $(".no-results").hide();
  }

  showGraphLegend() {
    $(".graph-view .legend").show();
  }

  hideGraphLegend() {
    $(".graph-view .legend").hide();
  }

  hideGraphAbsent() {
    $(".graph-view .absent").hide();
  }

  showFilters(){
      $('.table-view .messaging-and-controls, .module:not(".search-module"), .divider').css('visibility', 'visible');
  }

  hideFilters(){
     $('.table-view .messaging-and-controls, .module:not(".search-module"), .divider').css('visibility', 'hidden');
  }

}

let GeneDive = new Controller();

$(document).on('ready', function () {
  $('[data-toggle="tooltip"]').tooltip();

  // Mirror Adjacency Matrix
  for ( let gene in adjacency_matrix ) {
    for ( let interactant in adjacency_matrix[gene] ) {

      if ( !(interactant in adjacency_matrix) ) {
        adjacency_matrix[interactant] = {};
      }

      if ( !(gene in adjacency_matrix[interactant]) ) {
        adjacency_matrix[interactant][gene] = true;
      }

    }
  }

});
<|endoftext|>


<commit_before>var map;
var page;
var page_size;
$(function() {

 	// Set up map widget
 	options = {
 		map_id: "map",
 		zoom: 12
 	}
 	map = new LeafletPolylineWidget(options);

 	// get page and page_size parameters
	var searchParams = new URLSearchParams(window.location.search)
	if (searchParams.has('page'))
        page = searchParams.get('page');
	if (searchParams.has('page_size'))
        page_size = searchParams.get('page_size');

 	// Retrieve ambulances via AJAX
 	retrieveAmbulances(ambulance_id)

});

function retrieveAmbulances(ambulance_id) {

	// Build url
	var url = APIBaseUrl + 'ambulance/' + ambulance_id + '/updates';
	if (page != null) {
        url += "?page=" + page;
        if (page_size != null)
            url += "&page_size=" + page_size;
    } else if (page_size != null)
            url += "?page_size=" + page_size;

    $.ajax({
        type: 'GET',
        datatype: "json",
        url: url,

        fail: function (msg) {

            alert('Could not retrieve data from API:' + msg)

        },

        success: function (data) {

            console.log('Got data from API')

            addAmbulanceRoute(data)

        }

    })
        .done(function (data) {
            if (console && console.log) {
                console.log("Done retrieving ambulance data from API");
            }
        });

}

function addMarker(map, update, layer) {

	// add marker
	map.addPoint(update.location.latitude, update.location.longitude, update.id, null, layer)
		.bindPopup('' + ambulance_status[update.status] + '
@' + update.timestamp)
		.on('mouseover',
			function(e){
				// open popup bubble
				this.openPopup().on('mouseout',
					function(e){
						this.closePopup();
					});
			});

}

function calculateDistanceHaversine(location1, location2, radius) {

	radius = radius || 6371e3;

	// convert latitude and longitude to radians first
    var lat1 = Math.PI * location1.latitude / 180;
    var lat2 = Math.PI * location2.latitude / 180;
    var d_phi = lat2 - lat1;
    var d_lambda = Math.PI * (location2.longitude - location1.longitude) / 180;

    var a = Math.sin(d_phi / 2) * Math.sin(d_phi / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(d_lambda / 2) * Math.sin(d_lambda / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    // console.log('|| {} - {} ||= {}'.format(location2, location1, earth_radius * c))

    return radius * c;
}

function breakSegments(data, separationRadius, smallInterval) {

	separationRadius = separationRadius || 100;
	smallInterval = smallInterval || 2 * 60 * 1000; // 2 minutes

	var segments = [];

	var currentSegment = [];
	var lastPosition = null;
	var n = data.length;
	for (var i = 0; i < n; i++) {

		// current position
		var currentPosition = data[i];

		// distance?
		if (lastPosition != null) {
			var distance = calculateDistanceHaversine(lastPosition.location, currentPosition.location);
			var interval = Math.abs(Date.parse(lastPosition.timestamp) - Date.parse(currentPosition.timestamp));
			if (interval > smallInterval && distance > separationRadius) {
                // terminate current segment
                segments.push(currentSegment);
                currentSegment = [];
            }
		}

		// add position to segment
		currentSegment.push(currentPosition);

		// update lastPosition
		lastPosition = currentPosition;
	}

	// anything left?
	if (currentSegment.length > 0) {
        // terminate last segment
        segments.push(currentSegment);
    }

	return segments;

}

function addSegment(updates, layer) {

	// Add status markers
	// TODO: color depending on status

    // Create layer
    this.map.createLayer(layer);

	// First entry
	var lastStatus;
	if (updates.length >= 2) {

		// Retrieve last entry (first position)
		entry = updates[updates.length - 1];

		// add marker
		addMarker(map, entry, layer);

		// entry status
		lastStatus = entry.status;

	}

	// Mid updates
	for (var i = updates.length - 2; i > 0; i--) {

		// Retrieve next entry
		entry = updates[i];

		if (entry.status != lastStatus) {

            // add marker
            addMarker(map, entry, layer);

        }

		// entry status
		lastStatus = entry.status;

	}

	// Last entry
	if (updates.length > 0) {

		// Retrieve last entry (first position)
		entry = updates[0];

		// add marker
		addMarker(map, entry, layer);

	}

	// Store data in an array
	var latlngs = [];
	updates.forEach(function(update) {

		// push location
		var loc = update.location;
		latlngs.push([loc.latitude, loc.longitude]);

    });

	// Add line to map
	console.log('Adding segment');
	map.addLine(latlngs, 1, "red", null, layer);

}

// Interact with widget to add an ambulance route
function addAmbulanceRoute(data) {

    // short return
    if (data.results.length == 0)
        return;

    // break segments
    var segments = breakSegments(data.results);

    // loop on segments
    segments.forEach( function(segment, index) {

        // add segment to map
        addSegment(segment, 'layer_' + index);

    });

    // create route filter
    createRouteFilter(segments);

    console.log('Centering map');
    map.center(data.results[0].location);

}

function createRouteFilter(segments) {

    // Add the checkbox on the top right corner for filtering.
    var container = L.DomUtil.create('div', 'filter-options');

    //Generate HTML code for checkboxes for each of the statuses.
    var filterHtml = "";

    filterHtml += '
';
    segments.forEach(function (segment, index) {

        // categoryGroupLayers[index] = L.layerGroup(markersByCategory[index]);
        // categoryGroupLayers[index].addTo(map.map);

        filterHtml += '
'
            + '<input class="chk" data-status="layer_' + index + '" type="checkbox" value="" checked >'
            + index
            + ''
            + '
';

    });
    filterHtml += "
";

    // Append html code to container
    container.innerHTML = filterHtml;

    // Add the checkboxes.
    var customControl = L.Control.extend({

        options: {
            position: 'topright'
        },

        onAdd: function (map) {
            return container;
        }

    });
    map.map.addControl(new customControl());

    // Add listener to remove status layer when filter checkbox is clicked
    $('.chk').change(function () {

        // Which layer?
        var layer = this.map.getLayerPane(this.getAttribute('data-status'));

        if (this.checked) {
            layer.style.show();
        } else {
            layer.style.hide();
        }

    });

};
<commit_msg>Filtering routes in ambulance detail.<commit_after>var map;
var page;
var page_size;
$(function() {

 	// Set up map widget
 	options = {
 		map_id: "map",
 		zoom: 12
 	}
 	map = new LeafletPolylineWidget(options);

 	// get page and page_size parameters
	var searchParams = new URLSearchParams(window.location.search)
	if (searchParams.has('page'))
        page = searchParams.get('page');
	if (searchParams.has('page_size'))
        page_size = searchParams.get('page_size');

 	// Retrieve ambulances via AJAX
 	retrieveAmbulances(ambulance_id)

});

function retrieveAmbulances(ambulance_id) {

	// Build url
	var url = APIBaseUrl + 'ambulance/' + ambulance_id + '/updates';
	if (page != null) {
        url += "?page=" + page;
        if (page_size != null)
            url += "&page_size=" + page_size;
    } else if (page_size != null)
            url += "?page_size=" + page_size;

    $.ajax({
        type: 'GET',
        datatype: "json",
        url: url,

        fail: function (msg) {

            alert('Could not retrieve data from API:' + msg)

        },

        success: function (data) {

            console.log('Got data from API')

            addAmbulanceRoute(data)

        }

    })
        .done(function (data) {
            if (console && console.log) {
                console.log("Done retrieving ambulance data from API");
            }
        });

}

function addMarker(map, update, layer) {

	// add marker
	map.addPoint(update.location.latitude, update.location.longitude, update.id, null, layer)
		.bindPopup('' + ambulance_status[update.status] + '
@' + update.timestamp)
		.on('mouseover',
			function(e){
				// open popup bubble
				this.openPopup().on('mouseout',
					function(e){
						this.closePopup();
					});
			});

}

function calculateDistanceHaversine(location1, location2, radius) {

	radius = radius || 6371e3;

	// convert latitude and longitude to radians first
    var lat1 = Math.PI * location1.latitude / 180;
    var lat2 = Math.PI * location2.latitude / 180;
    var d_phi = lat2 - lat1;
    var d_lambda = Math.PI * (location2.longitude - location1.longitude) / 180;

    var a = Math.sin(d_phi / 2) * Math.sin(d_phi / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(d_lambda / 2) * Math.sin(d_lambda / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    // console.log('|| {} - {} ||= {}'.format(location2, location1, earth_radius * c))

    return radius * c;
}

function breakSegments(data, separationRadius, smallInterval) {

	separationRadius = separationRadius || 100;
	smallInterval = smallInterval || 2 * 60 * 1000; // 2 minutes

	var segments = [];

	var currentSegment = [];
	var lastPosition = null;
	var n = data.length;
	for (var i = 0; i < n; i++) {

		// current position
		var currentPosition = data[i];

		// distance?
		if (lastPosition != null) {
			var distance = calculateDistanceHaversine(lastPosition.location, currentPosition.location);
			var interval = Math.abs(Date.parse(lastPosition.timestamp) - Date.parse(currentPosition.timestamp));
			if (interval > smallInterval && distance > separationRadius) {
                // terminate current segment
                segments.push(currentSegment);
                currentSegment = [];
            }
		}

		// add position to segment
		currentSegment.push(currentPosition);

		// update lastPosition
		lastPosition = currentPosition;
	}

	// anything left?
	if (currentSegment.length > 0) {
        // terminate last segment
        segments.push(currentSegment);
    }

	return segments;

}

function addSegment(updates, layer) {

	// Add status markers
	// TODO: color depending on status

    // Create layer
    map.createLayer(layer);

	// First entry
	var lastStatus;
	if (updates.length >= 2) {

		// Retrieve last entry (first position)
		entry = updates[updates.length - 1];

		// add marker
		addMarker(map, entry, layer);

		// entry status
		lastStatus = entry.status;

	}

	// Mid updates
	for (var i = updates.length - 2; i > 0; i--) {

		// Retrieve next entry
		entry = updates[i];

		if (entry.status != lastStatus) {

            // add marker
            addMarker(map, entry, layer);

        }

		// entry status
		lastStatus = entry.status;

	}

	// Last entry
	if (updates.length > 0) {

		// Retrieve last entry (first position)
		entry = updates[0];

		// add marker
		addMarker(map, entry, layer);

	}

	// Store data in an array
	var latlngs = [];
	updates.forEach(function(update) {

		// push location
		var loc = update.location;
		latlngs.push([loc.latitude, loc.longitude]);

    });

	// Add line to map
	console.log('Adding segment');
	map.addLine(latlngs, 1, "red", null, layer);

}

// Interact with widget to add an ambulance route
function addAmbulanceRoute(data) {

    // short return
    if (data.results.length == 0)
        return;

    // break segments
    var segments = breakSegments(data.results);

    // loop on segments
    segments.forEach( function(segment, index) {

        // add segment to map
        addSegment(segment, 'layer_' + index);

    });

    // create route filter
    createRouteFilter(segments);

    console.log('Centering map');
    map.center(data.results[0].location);

}

function createRouteFilter(segments) {

    // Add the checkbox on the top right corner for filtering.
    var container = L.DomUtil.create('div', 'filter-options');

    //Generate HTML code for checkboxes for each of the statuses.
    var filterHtml = "";

    filterHtml += '
';
    segments.forEach(function (segment, index) {

        filterHtml += '
'
            + '<input class="chk" data-status="layer_' + index + '" type="checkbox" value="" checked >'
            + index
            + ''
            + '
';

    });
    filterHtml += "
";

    // Append html code to container
    container.innerHTML = filterHtml;

    // Add the checkboxes.
    var customControl = L.Control.extend({

        options: {
            position: 'topright'
        },

        onAdd: function (map) {
            return container;
        }

    });
    map.map.addControl(new customControl());

    // Add listener to remove status layer when filter checkbox is clicked
    $('.chk').change(function () {

        // Which layer?
        var layer = map.getLayerPane(this.getAttribute('data-status'));

        if (this.checked) {
            layer.style.show();
        } else {
            layer.style.hide();
        }

    });

};
<|endoftext|>


<commit_before>'use strict';

const assert = require('assert').strict;
const path = require('path');
const semver = require('semver');
const walk = require('fs-walk');
const digest = require('../lib/helpers.js').sri.digest;
const helpers = require('./test_helpers.js');

const config = helpers.getConfig();

const responses = {};

const expectedHeaders = {
    'accept-ranges': 'bytes',
    'access-control-allow-origin': '*',
    'cache-control': 'max-age=31536000',
    'connection': 'Keep-Alive',
    'content-length': '',
    'date': '',
    'etag': '',
    'last-modified': '',
    'vary': 'Accept-Encoding',
    'x-cache': '',
    'x-hello-human': 'Say hello back! @getBootstrapCDN on Twitter'
};

const compressedExtensions = [
    'css',
    'eot',
    'js',
    'map',
    'otf',
    'svg',
    'ttf',
    'woff',
    'woff2'
];

const CONTENT_TYPE_MAP = {
    css: 'text/css; charset=utf-8',
    js: 'application/javascript; charset=utf-8',

    map: 'application/json; charset=utf-8',

    // images
    png: 'image/png',
    svg: 'image/svg+xml',

    // fonts
    eot: 'application/vnd.ms-fontobject',
    otf: 'application/x-font-otf',
    ttf: 'application/x-font-ttf',
    woff: 'application/font-woff',
    woff2: 'application/font-woff2'
};

// Helper functions used in this file
function domainCheck(uri) {
    if (typeof process.env.TEST_S3 === 'undefined') {
        return uri;
    }

    return uri.replace('https://stackpath.bootstrapcdn.com/', process.env.TEST_S3);
}

function request(uri, cb) {
    // return memoized response to avoid making the same http call twice
    if (Object.prototype.hasOwnProperty.call(responses, uri)) {
        return cb(responses[uri]);
    }

    // build memoized response
    return helpers.prefetch(uri, (res) => {
        responses[uri] = res;
        cb(res);
    });
}

function assertSRI(uri, actualSri, done) {
    const expectedSri = digest(responses[uri].body, true);

    assert.strictEqual(actualSri, expectedSri);
    done();
}

const s3include = ['content-type'];

function assertHeaders(uri) {
    const ext = helpers.getExtension(uri);

    Object.keys(expectedHeaders).forEach((header) => {
        if (typeof process.env.TEST_S3 !== 'undefined' && !s3include.includes(header)) {
            it.skip(`has ${header}`);
        } else {
            it(`has ${header}`, (done) => {
                assert.ok(Object.prototype.hasOwnProperty.call(responses[uri].headers, header),
                    `Expects "${header}" in: ${Object.keys(responses[uri].headers).join(', ')}`);

                // Ignore case in checking equality.
                const actual = responses[uri].headers[header].toLowerCase();

                if (expectedHeaders[header] !== '') {
                    const expected = expectedHeaders[header].toLowerCase();

                    assert.strictEqual(actual, expected);
                }
                done();
            });
        }
    });

    if (compressedExtensions.includes(ext)) {
        it('has content-encoding: gzip', (done) => {
            assert.strictEqual(responses[uri].headers['content-encoding'], 'gzip');
            done();
        });
    } else {
        it('does NOT have content-encoding set', (done) => {
            // eslint-disable-next-line no-undefined
            assert.strictEqual(responses[uri].headers['content-encoding'], undefined);
            done();
        });
    }
}

function assertContentType(uri, currentType, cb) {
    const ext = helpers.getExtension(uri);
    const expectedType = CONTENT_TYPE_MAP[ext];

    assert.strictEqual(currentType, expectedType,
        `Invalid "content-type" for "${ext}", expects "${expectedType}" but got "${currentType}"`);
    cb();
}

describe('functional', () => {
    config.bootstrap.forEach((self) => {
        describe(domainCheck(self.javascript), () => {
            const uri = domainCheck(self.javascript);

            it('it works', (done) => {
                request(uri, (res) => {
                    helpers.assert.itWorks(res.statusCode, done);
                });
            });

            it('has integrity', (done) => {
                assertSRI(uri, self.javascriptSri, done);
            });
        });

        if (self.javascriptBundle) {
            describe(domainCheck(self.javascriptBundle), () => {
                const uri = domainCheck(self.javascriptBundle);

                it('it works', (done) => {
                    request(uri, (res) => {
                        helpers.assert.itWorks(res.statusCode, done);
                    });
                });

                it('has integrity', (done) => {
                    assertSRI(uri, self.javascriptBundleSri, done);
                });
            });
        }

        describe(domainCheck(self.stylesheet), () => {
            const uri = domainCheck(self.stylesheet);

            it('it works', (done) => {
                request(uri, (res) => {
                    helpers.assert.itWorks(res.statusCode, done);
                });
            });

            it('has integrity', (done) => {
                assertSRI(uri, self.stylesheetSri, done);
            });
        });
    });

    describe('bootswatch3', () => {
        config.bootswatch3.themes.forEach((theme) => {
            const uri = domainCheck(config.bootswatch3.bootstrap
                .replace('SWATCH_VERSION', config.bootswatch3.version)
                .replace('SWATCH_NAME', theme.name));

            describe(uri, () => {
                it('it works', (done) => {
                    request(uri, (res) => {
                        helpers.assert.itWorks(res.statusCode, done);
                    });
                });

                it('has integrity', (done) => {
                    assertSRI(uri, theme.sri, done);
                });
            });
        });
    });

    describe('bootswatch4', () => {
        config.bootswatch4.themes.forEach((theme) => {
            const uri = domainCheck(config.bootswatch4.bootstrap
                .replace('SWATCH_VERSION', config.bootswatch4.version)
                .replace('SWATCH_NAME', theme.name));

            describe(uri, () => {
                it('it works', (done) => {
                    request(uri, (res) => {
                        helpers.assert.itWorks(res.statusCode, done);
                    });
                });

                it('has integrity', (done) => {
                    assertSRI(uri, theme.sri, done);
                });
            });
        });
    });

    describe('bootlint', () => {
        config.bootlint.forEach((self) => {
            const uri = domainCheck(self.javascript);

            describe(uri, () => {
                it('it works', (done) => {
                    request(uri, (res) => {
                        helpers.assert.itWorks(res.statusCode, done);
                    });
                });

                it('has integrity', (done) => {
                    assertSRI(uri, self.javascriptSri, done);
                });
            });
        });
    });

    describe('fontawesome', () => {
        config.fontawesome.forEach((self) => {
            const uri = domainCheck(self.stylesheet);

            describe(uri, () => {
                it('it works', (done) => {
                    request(uri, (res) => {
                        helpers.assert.itWorks(res.statusCode, done);
                    });
                });

                it('has integrity', (done) => {
                    assertSRI(uri, self.stylesheetSri, done);
                });
            });
        });
    });

    describe('public/**/*.*', () => {
        // Build File List
        const whitelist = [
            'bootlint',
            'bootstrap',
            'bootswatch',
            'font-awesome',
            'twitter-bootstrap',
            'css',
            'js'
        ];
        const publicURIs = [];

        walk.filesSync(path.join(__dirname, '..', 'public'), (base, name) => {
            let root = base.split(`${path.sep}public${path.sep}`)[1];

            // ensure file is in whitelisted directory
            if (typeof root === 'undefined' || !whitelist.includes(root.split(path.sep)[0])) {
                return;
            }

            // replace Windows backslashes with forward ones
            root = root.replace(/\\/g, '/');
            const domain = domainCheck('https://stackpath.bootstrapcdn.com/');
            const uri = `${domain + root}/${name}`;

            // ignore twitter-bootstrap versions after 2.3.2
            if (uri.includes('twitter-bootstrap')) {
                const m = uri.match(/(\d+\.\d+\.\d+)/);

                // err on the side of testing things that can't be abstracted
                if (m && m[1] && semver.valid(m[1]) && semver.gt(m[1], '2.3.2')) {
                    return; // don't add the file
                }
            }

            publicURIs.push(uri);
        });

        // Run Tests
        for (const uri of publicURIs) {
            describe(uri, () => {
                it('it works', (done) => {
                    request(uri, (res) => {
                        helpers.assert.itWorks(res.statusCode, done);
                    });
                });

                assertHeaders(uri);

                it('has content-type', (done) => {
                    assertContentType(uri, responses[uri].headers['content-type'], done);
                });
            });
        }
    });
});
<commit_msg>Add missing changes from 0a91797.<commit_after>'use strict';

const assert = require('assert').strict;
const path = require('path');
const semver = require('semver');
const walk = require('fs-walk');
const digest = require('../lib/helpers.js').sri.digest;
const helpers = require('./test_helpers.js');

const config = helpers.getConfig();

const responses = {};

// Expects header names to be lowercase in this object.
const expectedHeaders = {
    'accept-ranges': 'bytes',
    'access-control-allow-origin': '*',
    'cache-control': 'max-age=31536000',
    'connection': 'Keep-Alive',
    'content-length': '',
    'date': '',
    'etag': '',
    'last-modified': '',
    'vary': 'Accept-Encoding',
    'x-cache': '',
    'x-hello-human': 'Say hello back! @getBootstrapCDN on Twitter'
};

const compressedExtensions = [
    'css',
    'eot',
    'js',
    'map',
    'otf',
    'svg',
    'ttf',
    'woff',
    'woff2'
];

const CONTENT_TYPE_MAP = {
    css: 'text/css; charset=utf-8',
    js: 'application/javascript; charset=utf-8',

    map: 'application/json; charset=utf-8',

    // images
    png: 'image/png',
    svg: 'image/svg+xml',

    // fonts
    eot: 'application/vnd.ms-fontobject',
    otf: 'application/x-font-otf',
    ttf: 'application/x-font-ttf',
    woff: 'application/font-woff',
    woff2: 'application/font-woff2'
};

// Helper functions used in this file
function domainCheck(uri) {
    if (typeof process.env.TEST_S3 === 'undefined') {
        return uri;
    }

    return uri.replace('https://stackpath.bootstrapcdn.com/', process.env.TEST_S3);
}

function request(uri, cb) {
    // return memoized response to avoid making the same http call twice
    if (Object.prototype.hasOwnProperty.call(responses, uri)) {
        return cb(responses[uri]);
    }

    // build memoized response
    return helpers.prefetch(uri, (res) => {
        responses[uri] = res;
        cb(res);
    });
}

function assertSRI(uri, actualSri, done) {
    const expectedSri = digest(responses[uri].body, true);

    assert.strictEqual(actualSri, expectedSri);
    done();
}

const s3include = ['content-type'];

function assertHeaders(uri) {
    const ext = helpers.getExtension(uri);

    Object.keys(expectedHeaders).forEach((header) => {
        header = header.toLowerCase();

        if (typeof process.env.TEST_S3 !== 'undefined' && !s3include.includes(header)) {
            it.skip(`has ${header}`);
        } else {
            it(`has ${header}`, (done) => {
                assert.ok(Object.prototype.hasOwnProperty.call(responses[uri].headers, header),
                    `Expects "${header}" in: ${Object.keys(responses[uri].headers).join(', ')}`);

                // Ignore case in checking equality.
                const actual = responses[uri].headers[header].toLowerCase();

                if (expectedHeaders[header] !== '') {
                    const expected = expectedHeaders[header].toLowerCase();

                    assert.strictEqual(actual, expected);
                }
                done();
            });
        }
    });

    if (compressedExtensions.includes(ext)) {
        it('has content-encoding: gzip', (done) => {
            assert.strictEqual(responses[uri].headers['content-encoding'], 'gzip');
            done();
        });
    } else {
        it('does NOT have content-encoding set', (done) => {
            // eslint-disable-next-line no-undefined
            assert.strictEqual(responses[uri].headers['content-encoding'], undefined);
            done();
        });
    }
}

function assertContentType(uri, currentType, cb) {
    const ext = helpers.getExtension(uri);
    const expectedType = CONTENT_TYPE_MAP[ext];

    assert.strictEqual(currentType, expectedType,
        `Invalid "content-type" for "${ext}", expects "${expectedType}" but got "${currentType}"`);
    cb();
}

describe('functional', () => {
    config.bootstrap.forEach((self) => {
        describe(domainCheck(self.javascript), () => {
            const uri = domainCheck(self.javascript);

            it('it works', (done) => {
                request(uri, (res) => {
                    helpers.assert.itWorks(res.statusCode, done);
                });
            });

            it('has integrity', (done) => {
                assertSRI(uri, self.javascriptSri, done);
            });
        });

        if (self.javascriptBundle) {
            describe(domainCheck(self.javascriptBundle), () => {
                const uri = domainCheck(self.javascriptBundle);

                it('it works', (done) => {
                    request(uri, (res) => {
                        helpers.assert.itWorks(res.statusCode, done);
                    });
                });

                it('has integrity', (done) => {
                    assertSRI(uri, self.javascriptBundleSri, done);
                });
            });
        }

        describe(domainCheck(self.stylesheet), () => {
            const uri = domainCheck(self.stylesheet);

            it('it works', (done) => {
                request(uri, (res) => {
                    helpers.assert.itWorks(res.statusCode, done);
                });
            });

            it('has integrity', (done) => {
                assertSRI(uri, self.stylesheetSri, done);
            });
        });
    });

    describe('bootswatch3', () => {
        config.bootswatch3.themes.forEach((theme) => {
            const uri = domainCheck(config.bootswatch3.bootstrap
                .replace('SWATCH_VERSION', config.bootswatch3.version)
                .replace('SWATCH_NAME', theme.name));

            describe(uri, () => {
                it('it works', (done) => {
                    request(uri, (res) => {
                        helpers.assert.itWorks(res.statusCode, done);
                    });
                });

                it('has integrity', (done) => {
                    assertSRI(uri, theme.sri, done);
                });
            });
        });
    });

    describe('bootswatch4', () => {
        config.bootswatch4.themes.forEach((theme) => {
            const uri = domainCheck(config.bootswatch4.bootstrap
                .replace('SWATCH_VERSION', config.bootswatch4.version)
                .replace('SWATCH_NAME', theme.name));

            describe(uri, () => {
                it('it works', (done) => {
                    request(uri, (res) => {
                        helpers.assert.itWorks(res.statusCode, done);
                    });
                });

                it('has integrity', (done) => {
                    assertSRI(uri, theme.sri, done);
                });
            });
        });
    });

    describe('bootlint', () => {
        config.bootlint.forEach((self) => {
            const uri = domainCheck(self.javascript);

            describe(uri, () => {
                it('it works', (done) => {
                    request(uri, (res) => {
                        helpers.assert.itWorks(res.statusCode, done);
                    });
                });

                it('has integrity', (done) => {
                    assertSRI(uri, self.javascriptSri, done);
                });
            });
        });
    });

    describe('fontawesome', () => {
        config.fontawesome.forEach((self) => {
            const uri = domainCheck(self.stylesheet);

            describe(uri, () => {
                it('it works', (done) => {
                    request(uri, (res) => {
                        helpers.assert.itWorks(res.statusCode, done);
                    });
                });

                it('has integrity', (done) => {
                    assertSRI(uri, self.stylesheetSri, done);
                });
            });
        });
    });

    describe('public/**/*.*', () => {
        // Build File List
        const whitelist = [
            'bootlint',
            'bootstrap',
            'bootswatch',
            'font-awesome',
            'twitter-bootstrap',
            'css',
            'js'
        ];
        const publicURIs = [];

        walk.filesSync(path.join(__dirname, '..', 'public'), (base, name) => {
            let root = base.split(`${path.sep}public${path.sep}`)[1];

            // ensure file is in whitelisted directory
            if (typeof root === 'undefined' || !whitelist.includes(root.split(path.sep)[0])) {
                return;
            }

            // replace Windows backslashes with forward ones
            root = root.replace(/\\/g, '/');
            const domain = domainCheck('https://stackpath.bootstrapcdn.com/');
            const uri = `${domain + root}/${name}`;

            // ignore twitter-bootstrap versions after 2.3.2
            if (uri.includes('twitter-bootstrap')) {
                const m = uri.match(/(\d+\.\d+\.\d+)/);

                // err on the side of testing things that can't be abstracted
                if (m && m[1] && semver.valid(m[1]) && semver.gt(m[1], '2.3.2')) {
                    return; // don't add the file
                }
            }

            publicURIs.push(uri);
        });

        // Run Tests
        for (const uri of publicURIs) {
            describe(uri, () => {
                it('it works', (done) => {
                    request(uri, (res) => {
                        helpers.assert.itWorks(res.statusCode, done);
                    });
                });

                assertHeaders(uri);

                it('has content-type', (done) => {
                    assertContentType(uri, responses[uri].headers['content-type'], done);
                });
            });
        }
    });
});
<|endoftext|>


<commit_before>/* global jQuery, CustomEvent */
/* jshint unused: false */

var browserDetection = (function ($) {
  "use strict";

  var app = {
    loc: location.href,
    baseUrl: location.href.substring(0, location.href.lastIndexOf('/'))
  };

  app.initialize = function() {
    if (this.isSupportedFirefox()) {
      $('#browser-firefox').show();
      $('#browser-unknown').hide();
    }
  };

  app.isSupportedFirefox = function() {
    var ua = navigator.userAgent.toLowerCase();
    // Unfortunately the only way of detecting Social API with website support
    // to add is by version number.
    var rvStart = ua.indexOf('rv:');
    var rvEnd = ua.indexOf(')', rvStart);
    var rv = parseInt(ua.substring(rvStart + 3, rvEnd), 10);
    return ua.contains('firefox') && rv > 23;
  };

  app.activateSocial = function(node, data) {
    data = data || {
      // currently required
      "name": "Talkilla",
      "iconURL": this.baseUrl + "/talkilla16.png",
      "icon32URL": this.baseUrl + "/talkilla32.png",
      "icon64URL": this.baseUrl + "/talkilla64.png",

      // at least one of these must be defined
      "sidebarURL": this.baseUrl + "/sidebar.html",

      // should be available for display purposes
      "description": "Talkilla Services",
      "author": "Mozilla",
      "homepageURL": "https://wiki.mozilla.org/Talkilla"
    };

    var event = new CustomEvent("ActivateSocialFeature");
    node.setAttribute("data-service", JSON.stringify(data));
    node.dispatchEvent(event);
  };

  return app;
})(jQuery);
<commit_msg>When visiting the index page, or adding social providers, if the site is not the main Talkilla demo site, indicate it in the title<commit_after>/* global jQuery, CustomEvent */
/* jshint unused: false */

var browserDetection = (function ($) {
  "use strict";

  var app = {
  };

  app.initialize = function() {
    if (this.isSupportedFirefox()) {
      $('#browser-firefox').show();
      $('#browser-unknown').hide();
    }

    $('.title').text($('.title').text() + this._getHostSpecificText());
  };

  app.isSupportedFirefox = function() {
    var ua = navigator.userAgent.toLowerCase();
    // Unfortunately the only way of detecting Social API with website support
    // to add is by version number.
    var rvStart = ua.indexOf('rv:');
    var rvEnd = ua.indexOf(')', rvStart);
    var rv = parseInt(ua.substring(rvStart + 3, rvEnd), 10);
    return ua.contains('firefox') && rv > 23;
  };

  app.activateSocial = function(node, data) {
    var baseUrl = location.href.substring(0, location.href.lastIndexOf('/'));

    data = data || {
      // currently required
      "name": "Talkilla" + this._getHostSpecificText(),
      "iconURL": baseUrl + "/talkilla16.png",
      "icon32URL": baseUrl + "/talkilla32.png",
      "icon64URL": baseUrl + "/talkilla64.png",

      // at least one of these must be defined
      "sidebarURL": baseUrl + "/sidebar.html",

      // should be available for display purposes
      "description": "Talkilla Services",
      "author": "Mozilla",
      "homepageURL": "https://wiki.mozilla.org/Talkilla"
    };

    var event = new CustomEvent("ActivateSocialFeature");
    node.setAttribute("data-service", JSON.stringify(data));
    node.dispatchEvent(event);
  };

  /**
   * This function looks to see if we're the main Talkilla site (currently
   * expected to be talkilla.mozillalabs.com) and if we're not, it will return
   * text that can be used to extend a string to specific where the site is.
   *
   * If the hostname is dotted, the function will return the first sub-domain
   * listed, otherwise it will return the whole hostname.
   */
  app._getHostSpecificText = function() {
    var hostname =
      location.hostname.substring(0, location.hostname.indexOf('.'));
    var result = location.hostname;
    if (hostname) {
      // If we're talkilla, no adaption necessary, just get out of here.
      if (hostname === 'talkilla')
        return "";

      if (!parseInt(hostname, 10))
        result = hostname;
    }
    return " (" + result + ")";
  };

  return app;
})(jQuery);
<|endoftext|>


<commit_before>
/*
 * This file is part of Invenio.
 * Copyright (C) 2013, 2014 CERN.
 *
 * Invenio is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * Invenio is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Invenio; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 */

define(function(require, exports, module) {
  'use strict';

  var $ = require('jquery'),
      tpl_file_entry = require('hgn!./templates/file_entry'),
      tpl_file_link = require('hgn!./templates/file_link'),
      tpl_flash_message = require('hgn!./templates/flash_message'),
      tpl_field_message = require('hgn!./templates/field_message');

  var PluploadWidget = function(element, options) {
    this.$element = $(element);
    this.options = $.extend({}, $.fn.pluploadWidget.defaults, options);

    this.init();
  };

  PluploadWidget.prototype = {

    constructor: PluploadWidget,

    init: function() {
    /*
     * Initialize plupload plugin for `element`.
     */

      var that = this,
          url = this.options.url,
          save_url = this.options.save_url,
          delete_url = this.options.delete_url,
          get_file_url = this.options.get_file_url,
          dropbox_url = this.options.dropbox_url,
          newdep_url = this.options.newdep_url,
          continue_url = this.options.continue_url;

      var $upload_start = this.$element.find('.upload-start'),
          $upload_stop = this.$element.find('.upload-stop'),
          $upload_speed = this.$element.find('.upload-speed'),
          $upload_filetable = this.$element.find('.upload-filetable'),
          $upload_filelist = this.$element.find('.upload-filelist');

      var had_error = false;

      this.uploader = new plupload.Uploader({
          // General settings
          runtimes : this.options.runtimes,
          url : url,
          max_file_size : this.options.max_file_size,
          chunk_size : this.options.chunk_size,
          unique_names : this.options.unique_names,
          browse_button : this.options.browse_button,
          drop_element : this.options.drop_element,
          filters : this.options.filters,
      });

      new plupload.QueueProgress();

      this.uploader.init();

      /**
       */

      function init_button_states(){
          $upload_start.addClass("disabled");
          $upload_stop.hide();
          $upload_start.show();
          $upload_speed.html('');
          had_error = false;
      }

      function redirect(){
          if(continue_url){
              if( window.location != continue_url ){
                  window.location = continue_url;
              }
          }
      }

      $upload_start.click(function(e) {
          e.preventDefault();

          $upload_start.addClass('disabled');
          $upload_start.hide();
          $upload_stop.show();

          if(that.uploader.files.length > 0){
              that.uploader.start();
          } else if (dropbox_files.length > 0) {
              start_dropbox_upload();
          }
      });

      $upload_stop.click(function(d){
          uploader.stop();
          $upload_stop.hide();
          $upload_start.show();
          $upload_start.removeClass('disabled');
          $.each(uploader.files, function(i, file) {
              if (file.loaded < file.size) {
                  $("#" + file.id + " .rmlink").show();
                  //$('#' + file.id + " .progress-bar").css('width', "0%");
              }
          });
          $upload_speed.html('');
          uploader.total.reset();
      });

      this.uploader.bind('FilesRemoved', function(up, files) {
          $.each(files, function(i, file) {
              $upload_filelist.find('#' + file.id).hide('fast', function(){
                  $upload_filelist.find('#' + file.id).remove();
                  if($upload_filelist.children().length === 0){
                      $upload_start.addClass("disabled");
                  }
              });
              if (file.status === plupload.DONE) { //If file has been successfully uploaded
                  $.ajax({
                      type: "POST",
                      url: delete_url,
                      data: $.param({
                          file_id: file.id
                      })
                  });
              }

          });
      });

      this.uploader.bind('UploadProgress', function(up, file) {
          $('#' + file.id + " .progress-bar").css('width', file.percent + "%");
          var upload_speed = that.getBytesWithUnit(up.total.bytesPerSec) + " per sec";
          console.log("Progress " + file.name + " - " + file.percent);
          $upload_speed.html(upload_speed);
          up.total.reset();
      });

      this.uploader.bind('UploadFile', function(up, file) {
          $('#' + file.id + " .rmlink").hide();
      });

      this.uploader.bind('FilesAdded', function(up, files) {
          var remove_files = [];
          $.each(up.files, function(i, file) {

          });

          that.$element.show();
          $upload_start.removeClass("disabled");
          $upload_filetable.show('slow');
          up.total.reset();
          var filename_already_exists = [];
          $.each(files, function(i, file) {
              // Check for existing file
              var removed = false;
              for(var j = 0; j<up.files.length; j++){
                  var existing_file = up.files[j];
                  if(existing_file.id != file.id && file.name == existing_file.name){
                      filename_already_exists.push(file.name);
                      up.removeFile(file);
                      removed = true;
                  }
              }
              if(!removed){
                  $upload_filelist.append(tpl_file_entry({
                          id: file.id,
                          filename: file.name,
                          filesize: that.getBytesWithUnit(file.size),
                          removeable: true,
                          progress: 0
                  }));
                  $('#' + file.id).show('fast');
                  $('#' + file.id + ' .rmlink').on("click", function(event){
                      up.removeFile(file);
                  });
              }
          });
          if(filename_already_exists.length > 0) {
              $upload_errors.hide();
              $upload_errors.append('
×Warning:' + filename_already_exists.join(", ") + " already exist.
");
              $upload_errors.show('fast');
          }
      });

      this.uploader.bind('FileUploaded', function(up, file, responseObj) {
          var res_data = {};

          try {
              res_data = JSON.parse(responseObj.response);
          } catch (err) {
              console.error(err);
          }

          file.server_id = res_data.id;

          $('#' + file.id + " .progress").removeClass("progress-striped");
          $('#' + file.id + " .progress-bar").css('width', "100%");
          $('#' + file.id + ' .rmlink').show();
          $('#' + file.id + " .progress").hide();
          $('#' + file.id + '_link').html(tpl_file_link({
              filename: file.name,
              download_url: get_file_url + "?file_id=" + res_data.id
          }));
          if (that.uploader.total.queued === 0)
              $upload_stop.hide();

          file.loaded = 0;
          $upload_speed.html('');
          up.total.reset();
      });

      function error_message(err) {
          var error_messages = {}, message, http_errors;

          error_messages[plupload.FILE_EXTENSION_ERROR] = "the file extensions is not allowed.";
          error_messages[plupload.FILE_SIZE_ERROR] = "the file is too big.";
          error_messages[plupload.GENERIC_ERROR] = "an unknown error.";
          error_messages[plupload.IO_ERROR] = "problems reading the file on disk.";
          error_messages[plupload.SECURITY_ERROR] = "problems reading the file on disk.";

          message = error_messages[err.code];

          if (message !== undefined) {
              return message;
          }

          if (err.code == plupload.HTTP_ERROR) {
              http_errors = {};
              http_errors[401] = "an authentication error. Please login first.";
              http_errors[403] = "lack of permissions.";
              http_errors[404] = "a server error.";
              http_errors[500] = "a server error.";

              message = http_errors[err.status];

              if (message !== undefined) {
                 return message;
              }
          }

          return "an unknown error occurred";
      }

      this.uploader.bind('Error', function(up, err) {
          had_error = true;
          var message = error_message(err);
          $upload_errors.hide();
          if (err.file){
              $('#' + err.file.id + " .progress").removeClass("progress-striped").addClass("progress-danger");
              $upload_errors.append(
                '
Error: Could not upload ' + err.file.name +" due to " + message + "
"
              );
          } else {
              $upload_errors.append(
                '
Error: ' + message + "
"
              );
          }
          $upload_errors.show('fast');
          $upload_start.addClass("disabled");
          $upload_stop.hide();
          $upload_start.show();
          up.refresh(); // Reposition Flash/Silverlight
      });

      this.uploader.bind('UploadComplete', function(up, files) {
        if(!had_error) {
          redirect();
        }
        init_button_states();
      });

      this.val(this.options.files);

      $upload_filelist.sortable({
          forcePlaceholderSize: true,
          forceHelperSizeType: true,
          handle: ".sortlink",
          start: function(event, ui) {
              $(ui.placeholder).show();
              $(ui.placeholder).html("				");
              $(ui.placeholder).css("visibility", "");
              var header_ths = $("#file-table thead th"),
                  item_tds = $(ui.helper).find("td"),
                  placeholder_tds = $(ui.placeholder).find("td");
              for(var i = 0; i < header_ths.length; i++){
                  $(item_tds[i]).width($(header_ths[i]).width());
                  $(placeholder_tds[i]).width($(header_ths[i]).width());
              }
          },
          update: function(event, ui){
              if (save_url) {
                  $(that.options.form_selector).trigger("dataSaveField", {
                    save_url: save_url,
                    name: "files",
                    value: that.val()
                  });
              }
          }
      });

      $upload_filelist.disableSelection();
    },

    getBytesWithUnit: function(bytes) {
      if( isNaN( bytes ) ){
            return '';
        }
      var units = [' bytes', ' KB', ' MB', ' GB'];
      var amountOf2s = Math.floor( Math.log( +bytes )/Math.log(2) );
      if( amountOf2s < 1 ){
        amountOf2s = 0;
      }
      var i = Math.floor( amountOf2s / 10 );
      bytes = +bytes / Math.pow( 2, 10*i );

      // Rounds to 2 decimals places.
        var bytes_to_fixed = bytes.toFixed(2);
        if( bytes.toString().length > bytes_to_fixed.toString().length ){
            bytes = bytes_to_fixed;
        }
      return bytes + units[i];
    },

    fake_file: function (file) {
      var plfile = new plupload.File({
          id: file.id,
          name: file.name,
          size: file.size
      });
      // Dont touch it!
      // For some reason the constructor doesn't initialize
      // the data members
      plfile.id = file.id;
      plfile.server_id = file.server_id || file.id;
      plfile.name = file.name;
      plfile.size = file.size;
      // loaded is set to 0 as a temporary fix plupload's bug in
      // calculating current upload speed. For checking if a file
      // has been uploaded, check file.status
      plfile.loaded = 0; //file.size;
      plfile.status = 5; //status = plupload.DONE
      plfile.percent = 100;
      return plfile;
    },

    val: function (value) {
      /* Set/get list of files from Plupload. */
      var that = this, ids, files, result,
          $upload_filetable = this.$element.find('.upload-filetable'),
          $upload_filelist = this.$element.find('.upload-filelist');

      if ( arguments.length ) {
          if (!$.isEmptyObject(value)) {
              $upload_filetable.show('slow');

              $.each(value, function(i, file) {
                  // Simulate a plupload file object
                  var plfile = that.fake_file(file);

                  that.uploader.files.push(plfile);
                  $upload_filelist.append(tpl_file_entry({
                      id: plfile.id,
                      filename: plfile.name,
                      filesize: that.getBytesWithUnit(plfile.size),
                      download_url: that.options.get_file_url + "?file_id=" + plfile.id,
                      removeable: true,
                      completed: true,
                  }));
                  $('#' + plfile.id).show('fast');
                  $("#" + plfile.id + " .rmlink").on("click", function(event) {
                      that.uploader.removeFile(plfile);
                  });
              });
          }

        return;
      }
      // Extract ids
      ids = this.$element.find('tr[id]').map(function(){ return $(this).attr('id');});
      // Build search dict
      files = {};
      $.each(this.uploader.files, function(idx, elem){
          files[elem.id] = elem;
      });
      // Build ordered list of server ids.
      result = [];
      $.each(ids, function(idx, id){
          var file = files[id];
          if(file !== undefined && file.status == 5) {
              result.push(file.server_id);
          }
      });
      return result;
    },

    connectEvents: function() {},

    onStart: function() {},

    onStop: function() {},

  };

  $.fn.pluploadWidget = function ( option ) {
    return this.each(function () {
      var $this = $(this),
          data = $this.data('pluploadWidget'),
          options = typeof option == 'object' && option;
      if (!data) {
        $this.data('pluploadWidget', (data = new PluploadWidget(this, options)));
      }
      if (typeof option == 'string') {
        data[option]();
      }
    });
  };

  $.fn.pluploadWidget.defaults = {
    files: null,
    runtimes: 'html5',
    chunksize: '10mb',
    unique_names : true,
    browse_button : 'pickfiles',
    drop_element : 'field-plupload_file',
    form_selector: "#submitForm",
    filters : {}
  };

  $.fn.pluploadWidget.Constructor = PluploadWidget;

});
<commit_msg>deposit: plupload error div selector addition<commit_after>
/*
 * This file is part of Invenio.
 * Copyright (C) 2013, 2014 CERN.
 *
 * Invenio is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * Invenio is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Invenio; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 */

define(function(require, exports, module) {
  'use strict';

  var $ = require('jquery'),
      tpl_file_entry = require('hgn!./templates/file_entry'),
      tpl_file_link = require('hgn!./templates/file_link'),
      tpl_flash_message = require('hgn!./templates/flash_message'),
      tpl_field_message = require('hgn!./templates/field_message');

  var PluploadWidget = function(element, options) {
    this.$element = $(element);
    this.options = $.extend({}, $.fn.pluploadWidget.defaults, options);

    this.init();
  };

  PluploadWidget.prototype = {

    constructor: PluploadWidget,

    init: function() {
    /*
     * Initialize plupload plugin for `element`.
     */

      var that = this,
          url = this.options.url,
          save_url = this.options.save_url,
          delete_url = this.options.delete_url,
          get_file_url = this.options.get_file_url,
          dropbox_url = this.options.dropbox_url,
          newdep_url = this.options.newdep_url,
          continue_url = this.options.continue_url;

      var $upload_start = this.$element.find('.upload-start'),
          $upload_stop = this.$element.find('.upload-stop'),
          $upload_speed = this.$element.find('.upload-speed'),
          $upload_filetable = this.$element.find('.upload-filetable'),
          $upload_filelist = this.$element.find('.upload-filelist'),
          $upload_errors = this.$element.find('.upload-errors');

      var had_error = false;

      this.uploader = new plupload.Uploader({
          // General settings
          runtimes : this.options.runtimes,
          url : url,
          max_file_size : this.options.max_file_size,
          chunk_size : this.options.chunk_size,
          unique_names : this.options.unique_names,
          browse_button : this.options.browse_button,
          drop_element : this.options.drop_element,
          filters : this.options.filters,
      });

      new plupload.QueueProgress();

      this.uploader.init();

      /**
       */

      function init_button_states(){
          $upload_start.addClass("disabled");
          $upload_stop.hide();
          $upload_start.show();
          $upload_speed.html('');
          had_error = false;
      }

      function redirect(){
          if(continue_url){
              if( window.location != continue_url ){
                  window.location = continue_url;
              }
          }
      }

      $upload_start.click(function(e) {
          e.preventDefault();

          $upload_start.addClass('disabled');
          $upload_start.hide();
          $upload_stop.show();

          if(that.uploader.files.length > 0){
              that.uploader.start();
          } else if (dropbox_files.length > 0) {
              start_dropbox_upload();
          }
      });

      $upload_stop.click(function(d){
          uploader.stop();
          $upload_stop.hide();
          $upload_start.show();
          $upload_start.removeClass('disabled');
          $.each(uploader.files, function(i, file) {
              if (file.loaded < file.size) {
                  $("#" + file.id + " .rmlink").show();
                  //$('#' + file.id + " .progress-bar").css('width', "0%");
              }
          });
          $upload_speed.html('');
          uploader.total.reset();
      });

      this.uploader.bind('FilesRemoved', function(up, files) {
          $.each(files, function(i, file) {
              $upload_filelist.find('#' + file.id).hide('fast', function(){
                  $upload_filelist.find('#' + file.id).remove();
                  if($upload_filelist.children().length === 0){
                      $upload_start.addClass("disabled");
                  }
              });
              if (file.status === plupload.DONE) { //If file has been successfully uploaded
                  $.ajax({
                      type: "POST",
                      url: delete_url,
                      data: $.param({
                          file_id: file.id
                      })
                  });
              }

          });
      });

      this.uploader.bind('UploadProgress', function(up, file) {
          $('#' + file.id + " .progress-bar").css('width', file.percent + "%");
          var upload_speed = that.getBytesWithUnit(up.total.bytesPerSec) + " per sec";
          console.log("Progress " + file.name + " - " + file.percent);
          $upload_speed.html(upload_speed);
          up.total.reset();
      });

      this.uploader.bind('UploadFile', function(up, file) {
          $('#' + file.id + " .rmlink").hide();
      });

      this.uploader.bind('FilesAdded', function(up, files) {
          var remove_files = [];
          $.each(up.files, function(i, file) {

          });

          that.$element.show();
          $upload_start.removeClass("disabled");
          $upload_filetable.show('slow');
          up.total.reset();
          var filename_already_exists = [];
          $.each(files, function(i, file) {
              // Check for existing file
              var removed = false;
              for(var j = 0; j<up.files.length; j++){
                  var existing_file = up.files[j];
                  if(existing_file.id != file.id && file.name == existing_file.name){
                      filename_already_exists.push(file.name);
                      up.removeFile(file);
                      removed = true;
                  }
              }
              if(!removed){
                  $upload_filelist.append(tpl_file_entry({
                          id: file.id,
                          filename: file.name,
                          filesize: that.getBytesWithUnit(file.size),
                          removeable: true,
                          progress: 0
                  }));
                  $('#' + file.id).show('fast');
                  $('#' + file.id + ' .rmlink').on("click", function(event){
                      up.removeFile(file);
                  });
              }
          });
          if(filename_already_exists.length > 0) {
              $upload_errors.hide();
              $upload_errors.append('
×Warning:' + filename_already_exists.join(", ") + " already exist.
");
              $upload_errors.show('fast');
          }
      });

      this.uploader.bind('FileUploaded', function(up, file, responseObj) {
          var res_data = {};

          try {
              res_data = JSON.parse(responseObj.response);
          } catch (err) {
              console.error(err);
          }

          file.server_id = res_data.id;

          $('#' + file.id + " .progress").removeClass("progress-striped");
          $('#' + file.id + " .progress-bar").css('width', "100%");
          $('#' + file.id + ' .rmlink').show();
          $('#' + file.id + " .progress").hide();
          $('#' + file.id + '_link').html(tpl_file_link({
              filename: file.name,
              download_url: get_file_url + "?file_id=" + res_data.id
          }));
          if (that.uploader.total.queued === 0)
              $upload_stop.hide();

          file.loaded = 0;
          $upload_speed.html('');
          up.total.reset();
      });

      function error_message(err) {
          var error_messages = {}, message, http_errors;

          error_messages[plupload.FILE_EXTENSION_ERROR] = "the file extensions is not allowed.";
          error_messages[plupload.FILE_SIZE_ERROR] = "the file is too big.";
          error_messages[plupload.GENERIC_ERROR] = "an unknown error.";
          error_messages[plupload.IO_ERROR] = "problems reading the file on disk.";
          error_messages[plupload.SECURITY_ERROR] = "problems reading the file on disk.";

          message = error_messages[err.code];

          if (message !== undefined) {
              return message;
          }

          if (err.code == plupload.HTTP_ERROR) {
              http_errors = {};
              http_errors[401] = "an authentication error. Please login first.";
              http_errors[403] = "lack of permissions.";
              http_errors[404] = "a server error.";
              http_errors[500] = "a server error.";

              message = http_errors[err.status];

              if (message !== undefined) {
                 return message;
              }
          }

          return "an unknown error occurred";
      }

      this.uploader.bind('Error', function(up, err) {
          had_error = true;
          var message = error_message(err);
          $upload_errors.hide();
          if (err.file){
              $('#' + err.file.id + " .progress").removeClass("progress-striped").addClass("progress-danger");
              $upload_errors.append(
                '
Error: Could not upload ' + err.file.name +" due to " + message + "
"
              );
          } else {
              $upload_errors.append(
                '
Error: ' + message + "
"
              );
          }
          $upload_errors.show('fast');
          $upload_start.addClass("disabled");
          $upload_stop.hide();
          $upload_start.show();
          up.refresh(); // Reposition Flash/Silverlight
      });

      this.uploader.bind('UploadComplete', function(up, files) {
        if(!had_error) {
          redirect();
        }
        init_button_states();
      });

      this.val(this.options.files);

      $upload_filelist.sortable({
          forcePlaceholderSize: true,
          forceHelperSizeType: true,
          handle: ".sortlink",
          start: function(event, ui) {
              $(ui.placeholder).show();
              $(ui.placeholder).html("				");
              $(ui.placeholder).css("visibility", "");
              var header_ths = $("#file-table thead th"),
                  item_tds = $(ui.helper).find("td"),
                  placeholder_tds = $(ui.placeholder).find("td");
              for(var i = 0; i < header_ths.length; i++){
                  $(item_tds[i]).width($(header_ths[i]).width());
                  $(placeholder_tds[i]).width($(header_ths[i]).width());
              }
          },
          update: function(event, ui){
              if (save_url) {
                  $(that.options.form_selector).trigger("dataSaveField", {
                    save_url: save_url,
                    name: "files",
                    value: that.val()
                  });
              }
          }
      });

      $upload_filelist.disableSelection();
    },

    getBytesWithUnit: function(bytes) {
      if( isNaN( bytes ) ){
            return '';
        }
      var units = [' bytes', ' KB', ' MB', ' GB'];
      var amountOf2s = Math.floor( Math.log( +bytes )/Math.log(2) );
      if( amountOf2s < 1 ){
        amountOf2s = 0;
      }
      var i = Math.floor( amountOf2s / 10 );
      bytes = +bytes / Math.pow( 2, 10*i );

      // Rounds to 2 decimals places.
        var bytes_to_fixed = bytes.toFixed(2);
        if( bytes.toString().length > bytes_to_fixed.toString().length ){
            bytes = bytes_to_fixed;
        }
      return bytes + units[i];
    },

    fake_file: function (file) {
      var plfile = new plupload.File({
          id: file.id,
          name: file.name,
          size: file.size
      });
      // Dont touch it!
      // For some reason the constructor doesn't initialize
      // the data members
      plfile.id = file.id;
      plfile.server_id = file.server_id || file.id;
      plfile.name = file.name;
      plfile.size = file.size;
      // loaded is set to 0 as a temporary fix plupload's bug in
      // calculating current upload speed. For checking if a file
      // has been uploaded, check file.status
      plfile.loaded = 0; //file.size;
      plfile.status = 5; //status = plupload.DONE
      plfile.percent = 100;
      return plfile;
    },

    val: function (value) {
      /* Set/get list of files from Plupload. */
      var that = this, ids, files, result,
          $upload_filetable = this.$element.find('.upload-filetable'),
          $upload_filelist = this.$element.find('.upload-filelist');

      if ( arguments.length ) {
          if (!$.isEmptyObject(value)) {
              $upload_filetable.show('slow');

              $.each(value, function(i, file) {
                  // Simulate a plupload file object
                  var plfile = that.fake_file(file);

                  that.uploader.files.push(plfile);
                  $upload_filelist.append(tpl_file_entry({
                      id: plfile.id,
                      filename: plfile.name,
                      filesize: that.getBytesWithUnit(plfile.size),
                      download_url: that.options.get_file_url + "?file_id=" + plfile.id,
                      removeable: true,
                      completed: true,
                  }));
                  $('#' + plfile.id).show('fast');
                  $("#" + plfile.id + " .rmlink").on("click", function(event) {
                      that.uploader.removeFile(plfile);
                  });
              });
          }

        return;
      }
      // Extract ids
      ids = this.$element.find('tr[id]').map(function(){ return $(this).attr('id');});
      // Build search dict
      files = {};
      $.each(this.uploader.files, function(idx, elem){
          files[elem.id] = elem;
      });
      // Build ordered list of server ids.
      result = [];
      $.each(ids, function(idx, id){
          var file = files[id];
          if(file !== undefined && file.status == 5) {
              result.push(file.server_id);
          }
      });
      return result;
    },

    connectEvents: function() {},

    onStart: function() {},

    onStop: function() {},

  };

  $.fn.pluploadWidget = function ( option ) {
    return this.each(function () {
      var $this = $(this),
          data = $this.data('pluploadWidget'),
          options = typeof option == 'object' && option;
      if (!data) {
        $this.data('pluploadWidget', (data = new PluploadWidget(this, options)));
      }
      if (typeof option == 'string') {
        data[option]();
      }
    });
  };

  $.fn.pluploadWidget.defaults = {
    files: null,
    runtimes: 'html5',
    chunksize: '10mb',
    unique_names : true,
    browse_button : 'pickfiles',
    drop_element : 'field-plupload_file',
    form_selector: "#submitForm",
    filters : {}
  };

  $.fn.pluploadWidget.Constructor = PluploadWidget;

});
<|endoftext|>


<commit_before>'use strict';

const request = require('request-promise');
const sinon = require('sinon');
require('sinon-as-promised');
const fs = require('fs');
const expect = require('chai').expect;
const yaml = require('js-yaml');

const getSwagger = require('../lib/getSwagger');

const res = fs.readFileSync('test/swagger.yaml', 'utf8');

const url = 'https://example.com/swagger.yaml';
const response = {
  swagger: '2.0'
};

describe('getSwagger', () => {
  beforeEach(() => {
    sinon.stub(request, 'get').resolves(res);
    sinon.stub(yaml, 'safeLoad').returns(response);
  });

  afterEach(() => {
    request.get.restore();
    yaml.safeLoad.restore();
  });

  it('should call request.get with url', () => {
    return getSwagger(url).then(() => {
      expect(request.get.called).to.be.true;
      expect(request.get.firstCall.args[0]).to.equal(url);
    });
  });

  it('should parse yaml and return result', () => {
    return getSwagger(url).then(result => {
      expect(yaml.safeLoad.called).to.be.true;
      expect(yaml.safeLoad.firstCall.args[0]).to.deep.equal(res);
      expect(result).to.deep.equal(response);
    });
  });

  it('should work with files');
});
<commit_msg>added test for files<commit_after>'use strict';

const request = require('request-promise');
const sinon = require('sinon');
require('sinon-as-promised');
const fs = require('fs');
const expect = require('chai').expect;
const yaml = require('js-yaml');

const getSwagger = require('../lib/getSwagger');

const res = fs.readFileSync('test/swagger.yaml', 'utf8');

const url = 'https://example.com/swagger.yaml';
const file = 'dist/swagger.yaml';
const response = {
  swagger: '2.0'
};

describe('getSwagger', () => {
  beforeEach(() => {
    sinon.stub(request, 'get').resolves(res);
    sinon.stub(yaml, 'safeLoad').returns(response);
    sinon.stub(fs, 'readFileSync').returns(res);
  });

  afterEach(() => {
    request.get.restore();
    yaml.safeLoad.restore();
    fs.readFileSync.restore();
  });

  it('should call request.get with url', () => {
    return getSwagger(url).then(() => {
      expect(request.get.called).to.be.true;
      expect(request.get.firstCall.args[0]).to.equal(url);
    });
  });

  it('should work with files', function () {
    return getSwagger(file).then(result => {
      expect(fs.readFileSync.called).to.be.true;
      expect(fs.readFileSync.firstCall.args[0]).to.equal(file);
    });
  });

  it('should parse yaml and return result', () => {
    return getSwagger(url).then(result => {
      expect(yaml.safeLoad.called).to.be.true;
      expect(yaml.safeLoad.firstCall.args[0]).to.deep.equal(res);
      expect(result).to.deep.equal(response);
    });
  });
});
<|endoftext|>